【问题标题】:Retrieving enum from ListBox SelectedItems property从 ListBox SelectedItems 属性中检索枚举
【发布时间】:2015-07-27 14:59:40
【问题描述】:

我定义了一个枚举,我的目的是在 ListBox 中向用户显示四个选项(无、左、中和右)。此 ListBox 将允许进行多项选择。单击保存命令后,我必须将选择传递给 ViewModel,在该视图模型中我将聚合选择并将其传递给 WCF 服务。

枚举:

[DataContract]
[Flags]
public enum Locations
{
    None = 0,
    [EnumMember]
    Left = 1,
    [EnumMember]
    Center = 2,
    [EnumMember]
    Right = 4,
    [EnumMember]
    LeftCenter = Left | Center,
    [EnumMember]
    LeftRight = Left | Right,
    [EnumMember]
    CenterRight = Center | Right,
    [EnumMember]
    All = Left | Center | Right
}

XAML:

<Button Command="{Binding SaveCommand}"
        CommandParameter="{Binding SelectedItems, ElementName=lbLocations}" />
<ListBox x:Name="lbLocations" SelectionMode="Multiple">
    <ListBoxItem Content="{x:Static m:Subsections.None}" />
    <ListBoxItem Content="{x:Static m:Subsections.Left}" />
    <ListBoxItem Content="{x:Static m:Subsections.Center}" />
    <ListBoxItem Content="{x:Static m:Subsections.Right}" />
</ListBox>

视图模型:

public ICommand SaveCommand
{
    get
    {
        if (_saveCommand == null)
            _saveCommand = new RelayCommand<IList>(x => Save(x));

         return _saveCommand;
    }
}

private void Save(IList locations)
{
    try
    {
        // ToList() produces InvalidCastException.
        var collection = locations.Cast<Locations>().ToList();

        // Do WCF stuff, display success, etc.
    }
    catch (Exception ex)
    {
        _dialogService.Show(ex.Message, "Error");
    }
}

我已成功地将选择作为 IList 传递回我的 ViewModel,但我很难将其转换回我的枚举。有没有更好的方法我忽略了,这可以工作吗?看来我快到了。

【问题讨论】:

    标签: .net wpf xaml mvvm enums


    【解决方案1】:

    尝试遍历转换后的列表并将值聚合到单个变量中,如下所示:

    private void Save(IList locations)
    {
        try
        {
            Locations location = Locations.None;
    
            foreach (Locations value in locations.Cast<Locations>())
            {
                location |= value;
            }
    
            // Do WCF stuff, display success, etc.
        }
        catch (Exception ex)
        {
            _dialogService.Show(ex.Message, "Error");
        }
    }
    

    【讨论】:

    • foreach 循环抛出与 ToList() 相同的 InvalidCastException。
    • 那么是Cast&lt;T&gt;()调用引发了异常,而不是ToList()?
    • 你查看IList的内容了吗?它包含什么?你试过OfType&lt;T&gt;()而不是Cast&lt;T&gt;()吗?
    • 我也是这么想的。但是异常本身让我认为您的IList 不包含Locations 类型的对象,或者至少不是里面的所有对象都属于那种类型......如果这只是一些流氓项目的问题,也许使用OfType&lt;T&gt;() 就足够了。
    • 这让我走上了正轨,IList 包含 ListBoxItem,我原以为会为我处理抽象,因为我相信 ListBoxItems 仍然是绑定到 ItemsSource 的项目的默认模板?无论如何,locations.Cast().Select(x => x.Content) 让我继续前进,但我也在评估 Glen 的解决方案。
    【解决方案2】:

    有更好的方法来实现这一点:

    创建一个类来保存ListBox 中每个项目的数据

    class EnumSelection
    {
        public bool IsSelected { get; set; }
    
        public Subsections Value { get; set; }
    
        public EnumSelection(Subsections value)
        {
            Value = value;
        }
    }
    

    ListBoxItemsSource 属性绑定到可用的枚举

    private IEnumerable<EnumSelection> enums;
    public IEnumerable<EnumSelection> Enums
    {
        get
        {
            if (this.enums == null)
            {
                this.enums = Enum.GetValues(typeof(Subsections)).Cast<Subsections>().Select(s => new EnumSelection(s));
            }
    
            return this.enums;
        }
    }
    
    public IEnumerable<EnumSelection> SelectedItems
    {
        get
        {
            return Enums.Where(e => e.IsSelected);
        }
    }
    

    使用 DataTemplate 绑定到新类

    <ListBox ItemsSource="{Binding Enums}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <CheckBox IsChecked="{Binding IsSelected}"/>
                    <TextBlock Text="{Binding Value}"/>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    

    保存方法:

    ICommand _saveCommand;
    public ICommand SaveCommand
    {
        get
        {
            return this._saveCommand
                   ?? (this._saveCommand = new RelayCommand<IEnumerable<EnumSelection>>(x => this.Save(x)));
        }
    }
    
    private void Save(IEnumerable<EnumSelection> enums)
    {
    }
    

    【讨论】:

      猜你喜欢
      • 2015-04-15
      • 2016-02-23
      • 2011-02-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-18
      相关资源
      最近更新 更多