C# - 具有可绑定属性的动态数量的类

问题描述:

我有X个RadioButton(Silverlight)。通常这个值在2-5之间。 称之为“开关”。每个单选按钮都绑定到该类的一个属性。C# - 具有可绑定属性的动态数量的类

示例属性看起来像

private bool _radio1; 
public bool Radio1{ 
set{ 
    _radio1 = value; 
    _radioX = !value; // make all others false 
} 
get{ return _radio1 } 
} 

的基本想法是,如果选择了一个无线电所有其他的都关掉。

我一直在使用其他方法尝试,这一次似乎最简单的相比,创建具有模板(尤其是当我在某些情况下,通过无线电涉及的其他按钮)

目前名单上有两个要求,我需要一个拥有2个属性(如男/女)复选框和3个属性。

未来可能会有更多,为什么我认为为X个单选按钮编写一个新班级是愚蠢的。

是否有任何使某些属性动态的方式?我看到了一些字典方法。

我看到这个方法 How do I create dynamic properties in C#?

我不知道怎么虽然绑定到它。

+0

将http://msdn.microsoft.com/en-us/library/system.dynamic.expandoobject.aspx展开对象与INotifyPropertyChanged有什么好处吗? – Luke 2011-05-19 19:41:06

尽管使用C#的动态特性很有趣,但在这种情况下并不需要。良好的老式数据绑定功能足以实现我们想要的功能。例如。下面是一些XAML结合的ItemsControl的集合与RadioButton模板:

<Grid> 
    <StackPanel> 
     <ItemsControl ItemsSource="{Binding}"> 
      <ItemsControl.ItemTemplate> 
       <DataTemplate> 
        <RadioButton 
         GroupName="Value" 
         Content="{Binding Description}" 
         IsChecked="{Binding IsChecked, Mode=TwoWay}"/> 
       </DataTemplate> 
      </ItemsControl.ItemTemplate> 
     </ItemsControl> 
     <TextBlock Text="{Binding SelectedItem}"/> 
    </StackPanel> 
</Grid> 

,这里是你如何在代码隐藏或从视图模型使用它:

DataContext = new CheckBoxValueCollection(new[] { "Foo", "Bar", "Baz" }); 

现在所有你需要的是让它工作的集合。这里是复选框值的集合:

public class CheckBoxValueCollection : ObservableCollection<CheckBoxValue> 
{ 
    public CheckBoxValueCollection(IEnumerable<string> values) 
    { 
     foreach (var value in values) 
     { 
      var checkBoxValue = new CheckBoxValue { Description = value }; 
      checkBoxValue.PropertyChanged += (s, e) => OnPropertyChanged(new PropertyChangedEventArgs("SelectedItem")); 
      this.Add(checkBoxValue); 
     } 
     this[0].IsChecked = true; 
    } 

    public string SelectedItem 
    { 
     get { return this.First(item => item.IsChecked).Description; } 
    } 
} 

而且这里的复选框值本身:

public class CheckBoxValue : INotifyPropertyChanged 
{ 
    private string description; 
    private bool isChecked; 

    public string Description 
    { 
     get { return description; } 
     set { description = value; OnPropertyChanged("Description"); } 
    } 
    public bool IsChecked 
    { 
     get { return isChecked; } 
     set { isChecked = value; OnPropertyChanged("IsChecked"); } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

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

现在你有一个完全动态的数据驱动和数据绑定友好的单选按钮的设计。

这里是什么样的程序是这样的:

enter image description here

收音机下面的文本显示当前选择的项目。尽管在本例中我使用了字符串,但您可以轻松地将设计更改为使用enum值或单选按钮描述的其他来源。

+0

如果您在其中一个复选框旁边,需要了解更多详细信息,该怎么办?如_天数_如果有人选择_days_复选框? – Luke 2011-05-19 20:49:38

+1

@Luke:如果复选框选择持续时间单位,我认为你只有一个输入字段的持续时间长度,而不是一个单独的小时,一个天等。即使这是你想要的,你可以添加持续时间长度复选框值,并将其绑定到模板。 – 2011-05-19 21:05:20

也许你应该尝试使用绑定到字典? (或与此一[串x]索引对象?)

事情是这样的:

public class AnyGroup : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    IDictionary<string, bool> _options; 
    public AnyGroup(IDictionary<string, bool> options) 
    { 
     this._options = options; 
    } 

    public bool this[string a] 
    { 
     get 
     { 
      return _options[a]; 
     } 
     set 
     { 
      if (value) 
      { 
       var other = _options.Where(p => p.Key != a).Select(p => p.Key).ToArray(); 
       foreach (string key in other) 
        _options[key] = false; 
       _options[a] = true; 

       if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Item[]")); 
      } 
      else 
       _options[a] = false;     
     } 
    }   
} 

而且绑定会是这样:

cbGroup.DataContext = new AnyGroup(new Dictionary<string, bool>() { {"male", true}, {"female", false} }); 

...

<StackPanel Name="cbGroup"> 
    <CheckBox IsChecked="{Binding [male], Mode=TwoWay}" /> 
    <CheckBox IsChecked="{Binding [female], Mode=TwoWay}" /> 
</StackPanel> 
+0

我会给它一个镜头。似乎是一个很好的处理方式。不知道我是否可以绑定到字典 - 以前没有做过。 – Luke 2011-05-19 20:51:10

+1

@Luke,我在提交之前用SL4检查了这个代码 - 它工作。 (但是我个人认为Rick的解决方案更具吸引力。) – Dmitry 2011-05-19 21:03:12