我与值转换器的数据绑定不起作用

发布于 2024-07-25 11:32:38 字数 2264 浏览 4 评论 0原文

我有一个简单的 Item 类,如下所示:

public class Item : DependencyObject
{
    public int No
    {
        get { return (int)GetValue(NoProperty); }
        set { SetValue(NoProperty, value); }
    }

    public string Name
    {
        get { return (string)GetValue(NameProperty); }
        set { SetValue(NameProperty, value); }
    }

    public static readonly DependencyProperty NoProperty = DependencyProperty.Register("No", typeof(int), typeof(Item));
    public static readonly DependencyProperty NameProperty = DependencyProperty.Register("Name", typeof(string), typeof(Item));
}

和一个 ValueConverter,如下所示:

[ValueConversion(typeof(Item), typeof(string))]
internal class ItemToStringConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null)
        {
            return null;
        }

        var item = ((Item)value);

        var sb = new StringBuilder();
        sb.AppendFormat("Item # {0}", item.No);

        if (string.IsNullOrEmpty(item.Name) == false)
        {
            sb.AppendFormat(" - [{0}]", item.Name);
        }

        return sb.ToString();
    }


    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

在我的 WPF 窗口上,我声明一个 DependencyProperty(称为 Items),它包含 Item 对象列表(List)。 )并使用此 XAML 代码创建一个绑定到此 DependencyProperty 的 ComboBox:

<ComboBox ItemsSource="{Binding ElementName=mainWindow, Path=Items}">
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Converter={StaticResource itemToStringConverter}}"/>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

如果我执行下面的代码一次,数据绑定工作正常,但是如果我再次执行它,值转换就会失败:

var item1 = new Item {Name = "Item A", No = 1};
var item2 = new Item {Name = "Item B", No = 2};
var item3 = new Item {Name = "Item C", No = 3};
Items = new List<Item> {item1, item2, item3};

问题是 ItemToStringConverter.Convert 方法现在传递的是字符串对象作为第一个参数而不是项目对象?

我究竟做错了什么?

问候, 肯尼思

I've got a simple Item-class, that looks like this:

public class Item : DependencyObject
{
    public int No
    {
        get { return (int)GetValue(NoProperty); }
        set { SetValue(NoProperty, value); }
    }

    public string Name
    {
        get { return (string)GetValue(NameProperty); }
        set { SetValue(NameProperty, value); }
    }

    public static readonly DependencyProperty NoProperty = DependencyProperty.Register("No", typeof(int), typeof(Item));
    public static readonly DependencyProperty NameProperty = DependencyProperty.Register("Name", typeof(string), typeof(Item));
}

And a ValueConverter, that looks like this:

[ValueConversion(typeof(Item), typeof(string))]
internal class ItemToStringConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null)
        {
            return null;
        }

        var item = ((Item)value);

        var sb = new StringBuilder();
        sb.AppendFormat("Item # {0}", item.No);

        if (string.IsNullOrEmpty(item.Name) == false)
        {
            sb.AppendFormat(" - [{0}]", item.Name);
        }

        return sb.ToString();
    }


    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

On my WPF Window, I declare a DependencyProperty (called Items) that holds a list of Item objects (List< Item >) and creates a ComboBox that binds to this DependencyProperty using this XAML-code:

<ComboBox ItemsSource="{Binding ElementName=mainWindow, Path=Items}">
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Converter={StaticResource itemToStringConverter}}"/>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

If I execute the code below once, the databinding works fine, howevery the value convertion fails if I execute it again:

var item1 = new Item {Name = "Item A", No = 1};
var item2 = new Item {Name = "Item B", No = 2};
var item3 = new Item {Name = "Item C", No = 3};
Items = new List<Item> {item1, item2, item3};

The problem is, that the ItemToStringConverter.Convert method is now passed a string-object as the first parameter instead of an Item-object?

What am I doing wrong?

Regards,
Kenneth

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

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

发布评论

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

评论(3

池木 2024-08-01 11:32:38

简单的解决方法是检查传递给 ValueConverter 的类型。 更改转换方法如下:

public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
        var item = value as Item;
        if(item == null) { return null; }
        var sb = new StringBuilder();
        sb.AppendFormat("Item # {0}", item.No);
        if(string.IsNullOrEmpty(item.Name) == false) {
            sb.AppendFormat(" - [{0}]", item.Name);
        }
        return sb.ToString();
    }

Simple workaround would be to check the type passed to your ValueConverter. Change Convert method as follows:

public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
        var item = value as Item;
        if(item == null) { return null; }
        var sb = new StringBuilder();
        sb.AppendFormat("Item # {0}", item.No);
        if(string.IsNullOrEmpty(item.Name) == false) {
            sb.AppendFormat(" - [{0}]", item.Name);
        }
        return sb.ToString();
    }
新人笑 2024-08-01 11:32:38

另一种方法是,

  1. 您可以从 Object 而不是 DependencyObject 派生类。
  2. 您可以实现 INotifyPropertyChange 接口
  3. ,并且可以实现只读属性,并在 No 或 Name 任何更改时触发通知事件。

公共类项目:System.ComponentModel.INotifyPropertyChanged
{

public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;


private void Notify(string p)
{
    if (PropertyChanged != null)
        PropertyChanged(this,
            new System.ComponentModel.PropertyChangedEventArgs(p));
}

private int _No = 0;
public int No
{
    get
    {
        return _No;
    }
    set
    {
        _No = value;
        Notify("No");
        Notify("DisplayName");
    }
}


private string _Name = "";
public string Name
{
    get
    {
        return _Name;
    }
    set
    {
        _Name = value;
        Notify("Name");
        Notify("DisplayName");
    }
}

public string DisplayName
{
    get
    {
        string sb = string.Format("Item # {0}", _No);
        if (!string.IsNullOrEmpty(_Name))
            sb += _Name;
        return sb;
    }
}

}

现在您只能绑定“DisplayName”属性而不是转换器。

  1. 转换器的实现非常复杂
  2. 并且基于 DependencyObject 的类只能用于 UI 目的

Alternative approach,

  1. You can derive your class from Object instead of DependencyObject
  2. You can implement INotifyPropertyChange interface
  3. And you can implement a read only property and fire notify event when any of No or Name changes.

public class Item : System.ComponentModel.INotifyPropertyChanged
{

public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;


private void Notify(string p)
{
    if (PropertyChanged != null)
        PropertyChanged(this,
            new System.ComponentModel.PropertyChangedEventArgs(p));
}

private int _No = 0;
public int No
{
    get
    {
        return _No;
    }
    set
    {
        _No = value;
        Notify("No");
        Notify("DisplayName");
    }
}


private string _Name = "";
public string Name
{
    get
    {
        return _Name;
    }
    set
    {
        _Name = value;
        Notify("Name");
        Notify("DisplayName");
    }
}

public string DisplayName
{
    get
    {
        string sb = string.Format("Item # {0}", _No);
        if (!string.IsNullOrEmpty(_Name))
            sb += _Name;
        return sb;
    }
}

}

Now you can only bind "DisplayName" property instead of converter..

  1. Converters are pretty complex to implement
  2. And DependencyObject based classes should only be used for UI purposes
失去的东西太少 2024-08-01 11:32:38

如果要使用数据绑定,则应将集合分配给 ItemsSource,而不是 Items。 我认为这可能会解决这个问题。

If you want to use databinding, you should assign your collection to ItemsSource, not Items. I think that would probably fix this problem.

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