使用 Silverlight 数据绑定确保列表中的项目是唯一的

发布于 2024-12-15 10:40:01 字数 912 浏览 1 评论 0原文

在我的 Silverlight 4 应用程序中,我有一个包含 element 列表的类 myClass。这个元素有一个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}" />
...

这样,对 elementName 的更改为自动传播回来。但是:我需要确保 NamemyClass.elements 中是唯一的(以及更多约束,具体取决于 myClass 的属性。

当然,元素不知道谁包含它(我认为它不应该知道),所以我的问题是:如何检查元素的约束(在名称属性的设置器中)? d 真的很喜欢使用Silverlight-数据绑定,因为它已经实现了错误通知,


坦率

in my Silverlight 4 application, I have a class myClass that contains a list of elements. This elements have a name-attribute that identifies them.

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

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

To display the list of elements, I databind myClass.elements to a Silverlight-Listbox:

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

This way, changes to the Name of the element is automatically propagated back. But: I need to make sure, that the Name is unique in myClass.elements (and some more constraints, depending on properties of myClass.

Naturally, the elements doesn't know who contains it (and it shouldn't know, I think). So my problem is: How can I check the contraints of the elements (in the setter of the Name-property)? I'd really like to use the Silverlight-Databinding, because it already implements Error Notification.

Thanks in advance,
Frank

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

和影子一齐双人舞 2024-12-22 10:40:01

我建议 element 应该实现 INotifyProperyChange,而 myClass 应该监听更改,然后检查重复项,要么抛出异常,要么通过 IDataErrorInfo、INotifyDataErrorInfo 或自定义指示器指示错误。 (所以你实现了观察者模式,我假设,这里的 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 并调用重复检查。

I'd suggest that element should implement INotifyProperyChange and myClass should be listening to changes, then checking for duplications, either throwing exceptions or indicating an error though IDataErrorInfo, INotifyDataErrorInfo or custom indicator. (so you implement Observer pattern, I assume, myClass here is an observer for its items).

For custom way, it's possible to set "IsDuplicate" property in duplicate items and bind it to background (red) color. That could be more useful for user, if s/he intentionally wants to set duplicate name here and then wants to fix some item entered before. Also if would be easier to find duplicates if you indicate all of them in the list.

UPDATE:

Here is indication of an error. Just changed item has border, duplicates for it - red font.

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

Here is item template, note ValidatesOnDataErrors:

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

Here is your Element class:

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; }
    }
}

And finally, myClass should listen to PropertyChanged and invoke duplication check.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文