繁体   English   中英

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

[英]How to bind to radio buttons created dynamically in WPF?

我在我正在使用的应用程序中使用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, 0, 0, 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, Type targetType, object parameter, 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);
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM