WPF MVVM在ItemsControl上使用单选按钮

17 浏览
0 Comments

WPF MVVM在ItemsControl上使用单选按钮

我之前曾将枚举绑定到单选按钮上,并且大体上了解它的工作原理。我使用了这个问题的备选实现:如何将单选按钮与枚举绑定?

与枚举不同,我想要在运行时生成一组用于自定义类型的运行时枚举,并将它们呈现为一组单选按钮。我已经在运行时枚举的集合上使用了一个 ListView 视图,并绑定了 ItemsSourceSelectedItem 属性,所以我的 ViewModel 已经正确连接。现在我正在尝试从 ListView 切换到带有单选按钮的 ItemsControl

这是我到了那里:

    



    
        
            
        
    

InstanceToBooleanConverter 的实现与那个问题中的 EnumToBooleanConverter 是相同的。这看起来没错,因为它似乎只是调用 Equals 方法:

public class InstanceToBooleanConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return value.Equals(parameter);
    }
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return value.Equals(true) ? parameter : Binding.DoNothing;
    }
}

我现在遇到的问题是,我不知道如何将运行时值作为 ConverterParameter 发送。当我尝试(使用上面的代码)时,我会收到以下错误:

不能在类型为“绑定”的“ConverterParameter”属性上设置“绑定”。只能在 DependencyObject 的 DependencyProperty 上设置“绑定”。

是否有一种方法可以绑定到项实例,并将其传递给 IValueConverter

admin 更改状态以发布 2023年5月20日
0
0 Comments

据我所知,使用MultiBinding没有好的方式可以实现这个操作,即使最初你认为有可能。因为你无法绑定ConverterParameter,因此你的ConvertBack实现没有所需的信息。\n\n我所做的是创建一个专门用于将枚举绑定到单选按钮的EnumModel类。在ItemsSource属性上使用转换器,然后你就可以将其绑定到EnumModel上了。EnumModel只是一个转接对象,使得绑定成为可能。它持有枚举的一个可能值以及对视图模型的引用,因此它可以将视图模型上的属性从布尔值翻译为对应的枚举值,反之亦然。\n\n下面是一个未经测试但通用的版本:


    
        
            
                
            
        
    

。\n\n转换器:

public class ToEnumModelsConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var viewmodel = value;
        var prop = viewmodel.GetType().GetProperty(parameter as string);
        List enumModels = new List();
        foreach(var enumValue in Enum.GetValues(prop.PropertyType))
        {
            var enumModel = new EnumModel(enumValue, viewmodel, prop);
            enumModels.Add(enumModel);
        }
        return enumModels;
    }
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

。\n\nEnumModel

public class EnumModel : INPC
{
    object enumValue;
    INotifyPropertyChanged viewmodel;
    PropertyInfo property;
    public EnumModel(object enumValue, object viewmodel, PropertyInfo property)
    {
        this.enumValue = enumValue;
        this.viewmodel = viewmodel as INotifyPropertyChanged;
        this.property = property;
        this.viewmodel.PropertyChanged += new PropertyChangedEventHandler(viewmodel_PropertyChanged);
    }
    void viewmodel_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == property.Name)
        {
            OnPropertyChanged("IsChecked");
        }
    }
    public bool IsChecked
    {
        get
        {
            return property.GetValue(viewmodel, null).Equals(enumValue);
        }
        set
        {
            if (value)
            {
                property.SetValue(viewmodel, enumValue, null);
            }
        }
    }
}

。\n\n为了演示一个我知道可用的代码示例(但仍然相当不成熟——仍在进行中!),你可以访问http://code.google.com/p/pdx/source/browse/trunk/PDX/PDX/Toolkit/EnumControl.xaml.cs。这仅适用于我的库的上下文环境,但它演示了基于DescriptionAttribute设置EnumModel的名称,这对你可能有用。

0
0 Comments

原来放弃使用ItemsControl,转而选择ListBox更加简单。

虽然ListBox可能更加重量级,但这主要是因为它为你完成了大量的任务。你可以很容易地在RadioButton.IsCheckedListBoxItem.IsSelected之间实现双向绑定。通过适当的控件模板,你可以很容易地摆脱所有选择视觉效果。


    
        
        
    
    
        
            
                
                
                    
                
            
        
    

0