加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 如何绑定到WPF中动态创建的单选按钮?

发布时间:2020-12-16 01:42:46 所属栏目:百科 来源:网络整理
导读:我在我正在使用的应用程序中使用 WPF和MVVM. 我正在动态创建5个单选按钮,在创建时我使用枚举和IValueConverter设置绑定. 这没关系,因为我知道我只需要5个单选按钮,但现在我需要创建的单选按钮的数量可以改变,它们可以是5,因为它们可能是30. 那么,这是将单选
我在我正在使用的应用程序中使用 WPF和MVVM.

我正在动态创建5个单选按钮,在创建时我使用枚举和IValueConverter设置绑定.

这没关系,因为我知道我只需要5个单选按钮,但现在我需要创建的单选按钮的数量可以改变,它们可以是5,因为它们可能是30.

那么,这是将单选按钮与代码绑定的最佳方法?我想我不能再使用枚举了,除非我设法动态创建枚举,我不知道是否有可能我读到有关动态枚举的内容……

谢谢.

编辑

这里或多或少是我用来动态创建单选按钮的代码.

public enum MappingOptions {
        Option0,Option1,Option2,Option3,Option4
    }
private MappingOptions mappingProperty; public MappingOptions MappingProperty { get { return mappingProperty; } set {
mappingProperty= value; base.RaisePropertyChanged("MappingProperty");
} }
private void CreateRadioButtons() { int limit = 5; int count = 0; string groupName = "groupName";
parent.FormWithRadioButtons.Children.Clear(); foreach (CustomValue value in AllCustomValues) { if (count < limit) { System.Windows.Controls.RadioButton tmpRadioBtn = new System.Windows.Controls.RadioButton(); tmpRadioBtn.DataContext = this; tmpRadioBtn.Content = value.Name; tmpRadioBtn.GroupName = groupName; tmpRadioBtn.Margin = new System.Windows.Thickness(10,5); string parameter = string.format("Option{0}",count.ToString());
System.Windows.Data.Binding tmpBinding = new System.Windows.Data.Binding("MappingProperty"); tmpBinding.Converter = new EnumBooleanConverter(); tmpBinding.ConverterParameter = parameter; tmpBinding.Source = this; try { tmpRadioBtn.SetBinding(System.Windows.Controls.RadioButton.IsCheckedProperty,tmpBinding); } catch (Exception ex) { //handle exeption }
parent.FormWithRadioButtons.Children.Add(tmpRadioBtn); count += 1; } else break; }
MappingProperty = MappingOptions.Option0; }
public class EnumBooleanConverter : IValueConverter { #region IValueConverter Members
public object Convert(object value,Type targetType,object parameter,System.Globalization.CultureInfo culture) { string parameterString = parameter as string; if (parameterString == null) return System.Windows.DependencyProperty.UnsetValue;
if (Enum.IsDefined(value.GetType(),value) == false) return System.Windows.DependencyProperty.UnsetValue;
object parameterValue = Enum.Parse(value.GetType(),parameterString);
return parameterValue.Equals(value); } public object ConvertBack(object value,System.Globalization.CultureInfo culture) { string parameterString = parameter as string;
if (parameterString == null) return System.Windows.DependencyProperty.UnsetValue;
return Enum.Parse(targetType,parameterString); }
#endregion }

解决方法

创建一个公开字符串Text和布尔IsChecked属性并实现INotifyPropertyChanged的类.叫它,哦,MutexViewModel.

创建另一个实现这些对象的可观察集合的类,称为Mutexes,并在每个对象上处理PropertyChanged – 例如有一个像这样的构造函数:

public MutexesViewModel(IEnumerable<MutexViewModel> mutexes)
{
   _Mutexes = new ObservableCollection<MutexViewModel>();
   foreach (MutexViewModel m in Mutexes)
   {
      _Mutexes.Add(m);
      m.PropertyChanged += MutexViewModel_PropertyChanged;
   }
}

和一个事件处理程序,确保在任何给定时间只有一个子对象的IsChecked设置为true:

private void MutexViewModel_PropertyChanged(object sender,PropertyChangedEventArgs e)
{
   MutexViewModel m = (MutexViewModel)sender;
   if (e.PropertyName != "IsChecked" || !m.IsChecked)
   {
     return;
   }
   foreach (MutexViewModel other in _Mutexes.Where(x: x != m))
   {
      other.IsChecked = false;
   }
}

您现在有一种机制可以创建任意数量的命名布尔属性,这些属性都是互斥的,即在任何给定时间只能有一个属性为真.

现在像这样创建XAML – 这个的DataContext是一个MutexesViewModel对象,但你也可以将ItemsSource绑定到类似{DynamicResource myMutexesViewModel.Mutexes}的东西.

<ItemsControl ItemsSource="{Binding Mutexes}">
   <ItemsControl.ItemTemplate>
      <DataTemplate DataType="local:MutexViewModel">
         <RadioButton Content="{Binding Text}" IsChecked="{Binding IsChecked,Mode=TwoWay}"/>
      </DataTemplate>
   </ItemsControl.ItemTemplate>
</ItemsControl>

编辑

我发布的XAML中存在语法错误,但没有什么可以让你完全停止.这些类有效:

public class MutexViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public string Text { get; set; }

    private bool _IsChecked;

    public bool IsChecked
    {
        get { return _IsChecked; }
        set
        {
            if (value != _IsChecked)
            {
                _IsChecked = value;
                OnPropertyChanged("IsChecked");
            }
        }
    }

    private void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler h = PropertyChanged;
        if (h != null)
        {
            h(this,new PropertyChangedEventArgs(propertyName));
        }
    }

}

public class MutexesViewModel
{
    public MutexesViewModel(IEnumerable<MutexViewModel>mutexes)
    {
        Mutexes = new ObservableCollection<MutexViewModel>(mutexes);
        foreach (var m in Mutexes)
        {
            m.PropertyChanged += MutexViewModel_PropertyChanged;
        }
    }

    private void MutexViewModel_PropertyChanged(object sender,PropertyChangedEventArgs e)
    {
        MutexViewModel m = (MutexViewModel) sender;
        if (e.PropertyName == "IsChecked" && m.IsChecked)
        {
            foreach(var other in Mutexes.Where(x => x != m))
            {
                other.IsChecked = false;
            }
        }
    }

    public ObservableCollection<MutexViewModel> Mutexes { get; set; }

}

创建一个项目,添加这些类,将ItemsControl XAML粘贴到主窗口的XAML中,并将其添加到主窗口的代码隐藏中:

public enum Test
    {
        Foo,Bar,Baz,Bat
    } ;

    public MainWindow()
    {
        InitializeComponent();

        var mutexes = Enumerable.Range(0,4)
            .Select(x => new MutexViewModel 
               { Text = Enum.GetName(typeof (Test),x) });

        DataContext = new MutexesViewModel(mutexes);
    }

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读