使用Silverlight数据绑定确保List中的唯一项

时间:2011-11-14 16:35:11

标签: silverlight list data-binding architecture class-design

在我的Silverlight 4应用程序中,我有一个类myClass,其中包含element个列表。这个element有一个name - 属性,用于标识它们。

class element
{
  string Name { get; set; }
}

class myClass
{
  List<element> elements { get; }
}

要显示元素列表,我将myClass.elements数据绑定到Silverlight-Listbox:

<ListBox>
  <ListBox.ItemTemplate>
    <DataTemplate>
      <Grid>
        <TextBox Text="{Binding Name, FallbackValue=[None], Mode=TwoWay,
                       NotifyOnValidationError=true, ValidatesOnExceptions=true}" />
...

这样,Name的{​​{1}}的更改会自动传播回来。但是:我需要确保element Name中的myClass.elements是唯一的(以及更多约束,具体取决于myClass的属性。

当然,元素不知道谁包含它(我认为它不应该知道)。所以我的问题是:如何检查元素的约束(在Name-property的setter中)?我真的很想使用Silverlight-Databinding,因为它已经实现了错误通知。

提前致谢,
弗兰克

1 个答案:

答案 0 :(得分:1)

我建议element应该实现INotifyProperyChange,myClass应该监听更改,然后检查重复,通过IDataErrorInfo,INotifyDataErrorInfo或自定义指示器抛出异常或指示错误。 (所以你实现了Observer模式,我假设,myClass这里是它的项目的观察者)。

对于自定义方式,可以在重复项中设置“IsDuplicate”属性并将其绑定到背景(红色)颜色。这对用户来说可能更有用,如果他/她有意在此处设置重复名称然后想要修复之前输入的某个项目。如果你在列表中指出所有副本,那么如果更容易找到重复项。

<强>更新

这是错误的指示。刚更改的项目有边框,重复项 - 红色字体。

<Style TargetType="{x:Type TextBox}">
    <Style.Triggers>
        <DataTrigger Binding="{Binding Path=IsDuplicate}" Value="True">
            <Setter Property="Foreground" Value="Red" />
        </DataTrigger>
        <Trigger Property="Validation.HasError" Value="true">
            <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, 
               Path=(Validation.Errors)[0].ErrorContent}"/>
            <Setter Property="BorderBrush" Value="Red"/>
        </Trigger>
    </Style.Triggers>
</Style>

这是项目模板,请注意ValidatesOnDataErrors

    <ListBox.ItemTemplate>
        <DataTemplate>
            <Grid>
                <TextBox Text="{Binding Path=Name, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnDataErrors=True}" />
            </Grid>
        </DataTemplate>
    </ListBox.ItemTemplate>

这是您的Element类:

class Element : INotifyPropertyChanged, IDataErrorInfo
{
    private string _name;
    public string Name
    {
        get { return _name; }
        set { _name = value;
        if(PropertyChanged != null)
            PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Name"));
        }
    }

    private bool _isDuplicate;
    public bool IsDuplicate
    {
        get { return _isDuplicate; }
        set
        {
            _isDuplicate = value;
            PropertyChanged.Invoke(this, new PropertyChangedEventArgs("IsDuplicate"));
        }
    }
    //IDataErrorInfo
    public event PropertyChangedEventHandler PropertyChanged;

    public string this[string columnName]
    {
        get 
        {
            if (IsDuplicate)
                return "Duplicate col" + columnName;
            return null;
        }
    }

    public string Error
    {
        get { return null; }
    }
}

最后,myClass应该监听PropertyChanged并调用重复检查。