簡體   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