gpt4 book ai didi

wpf - 如何在 MVVM 中将标志枚举绑定(bind)到 ListBox

转载 作者:行者123 更新时间:2023-12-04 17:28:18 24 4
gpt4 key购买 nike

我想将具有标志属性的枚举绑定(bind)到具有 mvvm 模式中的复选框项目模板的列表框?我怎样才能做到这一点?

[Flags]
public enum SportTypes
{
None = 0,
Baseball = 1,
Basketball = 2,
Football = 4,
Handball = 8,
Soccer = 16,
Volleyball = 32
}


<ListBox Name="checkboxList2"
ItemsSource="{Binding Sports}"

Margin="0,5"
SelectionMode="Multiple">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding Path=SportTypeEnum, Converter={StaticResource enumBooleanConverter}}"
Content="{Binding Item}"/>
</DataTemplate>

</ListBox.ItemTemplate>

最佳答案

您不能轻易地直接绑定(bind)该值,因为转换器无法从单个标志构建标志组合。所以你需要管理一个标志的集合,并基于这个集合构建组合。困难在于ListBox.SelectedItems属性是只读的。但是,this blog post使用附加属性提供了一个很好的解决方法。

这是使用此解决方案的完整示例:

代码隐藏

[Flags]
public enum MyEnum
{
Foo = 1,
Bar = 2,
Baz = 4
}

public partial class TestEnum : Window, INotifyPropertyChanged
{
public TestEnum()
{
InitializeComponent();
_flags = (MyEnum[])Enum.GetValues(typeof(MyEnum));
_selectedFlags = new ObservableCollection<MyEnum>();
_selectedFlags.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(_selectedFlags_CollectionChanged);
this.DataContext = this;
}

void _selectedFlags_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if (_selectedFlags.Count == 0)
Value = default(MyEnum);
else
Value = _selectedFlags.Aggregate((v, acc) => acc | v);
}

private MyEnum[] _flags;
public MyEnum[] Flags
{
get { return _flags; }
set
{
_flags = value;
OnPropertyChanged("Flags");
}
}

private ObservableCollection<MyEnum> _selectedFlags;
public ObservableCollection<MyEnum> SelectedFlags
{
get { return _selectedFlags; }
set
{
_selectedFlags = value;
OnPropertyChanged("SelectedFlags");
}
}

private MyEnum _value;
public MyEnum Value
{
get { return _value; }
set
{
_value = value;
OnPropertyChanged("Value");
var currentFlags = _flags.Where(f => _value.HasFlag(f));
var addedFlags = currentFlags.Except(_selectedFlags).ToArray();
var removedFlags = _selectedFlags.Except(currentFlags).ToArray();
foreach (var f in addedFlags)
{
_selectedFlags.Add(f);
}
foreach (var f in removedFlags)
{
_selectedFlags.Remove(f);
}
}
}

private DelegateCommand<MyEnum> _setValueCommand;
public ICommand SetValueCommand
{
get
{
if (_setValueCommand == null)
{
_setValueCommand = new DelegateCommand<MyEnum>(v => Value = v);
}
return _setValueCommand;
}
}

public event PropertyChangedEventHandler PropertyChanged;

protected virtual void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
}

XAML
<Window x:Class="TestPad.TestEnum"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:TestPad"
Title="TestEnum" Height="300" Width="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Text="{Binding Value}" />
<ListBox Grid.Row="1"
ItemsSource="{Binding Flags}"
SelectionMode="Extended"
my:MultiSelectorBehavior.SynchronizedSelectedItems="{Binding SelectedFlags}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding}" IsChecked="{Binding IsSelected, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListBoxItem}}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ItemsControl Grid.Row="2"
ItemsSource="{Binding Flags}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Command="{Binding DataContext.SetValueCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"
CommandParameter="{Binding}"
Content="{Binding}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Window>

注意:为简单起见,ViewModel 是 Window 类。在真正的 MVVM 应用程序中,您当然会使用单独的 ViewModel 类...

关于wpf - 如何在 MVVM 中将标志枚举绑定(bind)到 ListBox,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3474924/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com