WPF-创建可见性列表

时间:2014-05-19 22:28:32

标签: c# wpf mvvm visibility

此时此刻,我正在使用WPF和MVVM。我在UniformGrid中有30个按钮,每个按钮都有特定的DynamicResource和特定的内容(文本)。我需要管理每个按钮的可见性,但我不想为每个按钮执行变量。

我正在考虑创建一个可见性列表并绑定此列表。但是我不想丢失UniformGrid,只是我希望在不同的按钮中绑定列表的每个元素。

3 个答案:

答案 0 :(得分:1)

您可以通过指定索引直接绑定到列表中的项目。

<Button Content="Button 1" Visibility="{Binding Visibilities[0]}" />
<Button Content="Button 2" Visibility="{Binding Visibilities[1]}" />
<Button Content="Button 3" Visibility="{Binding Visibilities[2]}" />

在ViewModel

中定义可见性
Visibilities = new List<Visibility>()
{ Visibility.Visible, Visibility.Collapsed, Visibility.Visible};

您只需确保在更改列表中的值时引发PropertyChanged事件,以便控件注意到更改。

var handler = PropertyChanged;
if (handler != null)
{
    PropertyChanged(this, new PropertyChangedEventArgs("Visibilities"));
}

答案 1 :(得分:0)

编辑这很疯狂,请不要尝试。


这不适合胆小的人,但有一种可能性是使用运行时类型系统来实现自定义属性。您可以定制自定义类型以显示所需的属性,同时仍在内部维护可见性列表。使用这样的简单属性:

<Button Visibility="{Binding Visibilities.V1}" />
<Button Visibility="{Binding Visibilities.V2}" />

然后,您希望“Visibilities”对象实现一个实现“ICustomTypeProvider”的类,包装适当的数据(Visibility数组)。它还应该为底层值公开一个索引器,并且setter应该引发“PropertyChanged”:

public class VisibilitiesClass : ICustomTypeProvider, INotifyPropertyChanged
{
    public Visibility[] Visibilities { get; private set; };

    public VisibilitiesClass(int count) 
    {
        Visibilities = new Visibility[count];
        for (int i = 0; i < count; i++)
            Visibilities[i] = Visibility.Collapsed;
    }

    public Type GetCustomType()
    {
        return new VisibilitiesType(Visibilities.Length);
    }

    public Visibility this[int index]
    {
        get { return Visibilities[index]; }
        set
        {
            Visibilities[index] = value;
            RaisePropertyChanged("V" + index);
        }
    }
}

上面引用的VisibilitiesType应该扩展Type,并根据需要返回属性列表(“V1”,“V2”,...,“Vn”):

public class VisibilitiesType : Type
{
    private int _count;

    public VisibilitiesType(int count)
    {
        _count = count;
    }

    public override PropertyInfo[] GetProperties(BindingFlags bindingAttr)
    {
        return Enumerable.Range(1, _count).Select(i => new VisibilityProperty(i)).ToArray();
    }
}

最后,“VisibilityProperty”应该扩展“PropertyInfo”,并从宿主对象返回适当的值:

public class VisibilityProperty : PropertyInfo
{
    private int _index;

    public VisibilityProperty(int index)
    {
        _index = index;
    }

    public override string Name
    {
        get { return "V" + _index; }
    }

    public override object GetValue(object obj, BindingFlags invokeAttr, Binder binder, object[] index, CultureInfo culture)
    {
        var host = obj as VisibilitiesClass;
        return host[_index];
    }
}

请注意,上面的实现非常省略 - “Type”和“PropertyInfo”都有很多虚拟方法,其中一些可能需要覆盖。

答案 2 :(得分:0)

最好的解决方案是创建ExpandObject。

我创建了一个ExpandObject作为Dictonary

 var visibilitiesAsDictionary  = new ExpandoObject() as IDictionary<string, Object>;

然后我添加所有变量,在字符串中我把变量的名称和Object的值。

visibilitiesAsDictionary.Add("Item1", Visibility.Visible);
visibilitiesAsDictionary.Add("Item2", Visibility.Visible);

创建动态变量

之后
private dynamic _visibilities;
public dynamic Visibilities
    {
        get { return _visibilities; }
        set { _visibilities = value; RaisePropertyChanged("Visibilities"); }
    }

然后,

Visibilities = visibilitiesAsDictionary

在Xaml中我绑定了属性

<Button Command="{Binding Item1Command}" Visibility="{Binding Visibilities.Item1}">
<Button Command="{Binding Item2Command}" Visibility="{Binding Visibilities.Item2}">

因此,当我初始化Dictionary时,按顺序无关紧要,因为该属性将绑定特定名称。