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

时间:2011-05-19 19:38:26

标签: c# silverlight data-binding binding

我有X个RadioButtons(Silverlight)。通常这个值在2-5之间。 称之为“开关”。每个单选按钮都绑定到该类的属性。

示例属性类似于

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#?

我不知道如何绑定它。

2 个答案:

答案 0 :(得分:5)

虽然使用C#的动态功能很有趣,但在这种情况下不需要它。良好的老式数据绑定功能足以满足我们的需求。例如。以下是使用ItemsControl模板将RadioButton绑定到集合的一些XAML:

<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值或其他来源进行单选按钮说明。

答案 1 :(得分:1)

也许你应该尝试使用绑定到字典? (或者是带有[string 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>