【问题标题】:WPF UserControl Binding to CollectionWPF UserControl 绑定到集合
【发布时间】:2016-07-04 12:30:41
【问题描述】:

我的 UI 上有一个列表框,我的视图模型中有一个支持集合。 我一直在尝试对其进行数据绑定/数据模板化,以便如果在集合中添加了新项目,则会将新的用户控件添加到 UI。但是,我不能让它完全工作。 澄清一下,我可以根据集合中的项目数在 UI 上显示正确数量的控件,但不能将用户控件的属性绑定到集合中的项目。 这只是我最初试图弄清楚,然后在以后使它变得更加复杂,也许我现在遇到这个问题是件好事..

数据绑定 WPF 代码:

<ListBox x:Name="SubSystemList" ItemsSource="{Binding Path=SubSystems}">
    <ListBox.ItemTemplate>
        <DataTemplate DataType="{x:Type src:SubSystem}">
            <controls:SubSystem DeviceCount="{Binding Path=DeviceCount}" SystemName="{Binding Path=Name}" />
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

我试图渲染到的用户控件的属性:

public string SystemName
{
    get { return (string) GetValue(SubSystenNameProperty); }
    set { SetValue(SubSystenNameProperty, value); }
}
public int DeviceCount
{
    get { return (int) GetValue(DeviceCountProperty); }
    set { SetValue(DeviceCountProperty, value); }
}

我不愿意(直接..)发布更多代码,因为它只会变得更加难以理解。 设置器中的 Debug WriteLine 根本不会触发(断点不会被命中)。这让我认为这是一个路径/绑定问题。

任何帮助将不胜感激。

编辑 src:SubSystem 代码:​​(为清楚起见删除了附加属性)

public class SubSystem
{
    [XmlAttribute("Name")]
    [DataMember]
    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }

    [DataMember]
    public int DeviceCount
    {
        get { return _deviceCount; }
        set { _deviceCount = value; } 
    }
}

用户控件上的依赖属性:子系统

public static readonly DependencyProperty DeviceCountProperty = DependencyProperty.Register(
    nameof(DeviceCount), typeof(int), typeof(SubSystem));

public static readonly DependencyProperty SubSystenNameProperty = DependencyProperty.Register(
    nameof(SystemName), typeof(string), typeof(SubSystem));

另一个编辑

进一步的挠头在输出日志中发现了这一点:

em.Windows.Data Error: 40 : BindingExpression path error: 'SystemName' property not found on 'object' ''SubSystem' (HashCode=32985660)'. BindingExpression:Path=SystemName; DataItem='SubSystem' (HashCode=32985660); target element is 'TextBox' (Name=''); target property is 'Text' (type 'String')

让我觉得它不喜欢的用户控件代码背后/绑定中发生了一些事情,有趣的是,在我感到困惑之后,我将用户控件的名称更改为子系统控件,并确保所有绑定名称在uc是正确的。所以不知道为什么它完全这样做..进一步挖掘。

【问题讨论】:

  • 但是,DeviceCount 和 SystemName 是 DependencyProperty 吗?如果要将它们绑定到 UI,则应将它们定义为 Dependecy Properties。见 msdn:msdn.microsoft.com/en-us/library/ms752914(v=vs.100).aspx
  • 从视图模型中的后备集合绑定一种方式,上面的设置器在用户控件中(不同于视图模型对象等)
  • @Clemens 总是有很多学习,我不知道“XAML 解析器直接生成 GetValue/SetValue 调用”。但是我认为 OP 显示的细节很少,让我们了解问题出在哪里。
  • @cicciorocca 是的。 CLR 包装器的声明(如果它是一个)被破坏。
  • @cicciorocca 我实现了 INotifyPropertyChanged,但没有任何区别。我认为用户控件正在尝试访问 SubSystem 对象上的数据属性。错误说得很对,子系统对象(即视图模型)上不存在该属性。看起来像数据上下文/绑定路径问题..

标签: c# wpf xaml data-binding


【解决方案1】:

似乎您的依赖属性声明错误。

例如,string SystemName 依赖属性的完整声明如下所示:

public static readonly DependencyProperty SystemNameProperty =
    DependencyProperty.Register("SystemName", typeof(string), typeof(SubSystem));

public string SystemName
{
    get { return (string)GetValue(SystemNameProperty); }
    set { SetValue(SystemNameProperty, value); }
}

请注意,属性包装器中不应有除 GetValue/SetValue 之外的任何其他内容。如果您需要收到有关属性值更改的通知,您可以通过属性元数据注册一个 PropertyChangedCallback,并使用 Register 方法的另一个重载。

【讨论】:

  • 我认为这是一个问题。但它还没有解决绑定问题,我仍然无法将值输入到用户控件中。不过谢谢你,我没有意识到它需要不同的 getter/setter。
【解决方案2】:

我认为你应该:

  • 在您的 SubSystem 类中实现 InotifyPropertyChanged 接口。

  • DependencyProperties SystemName 和 DeviceCount 的 SetValue 和 GetValue

    公共类子系统:INotifyPropertyChanged { 公共事件 PropertyChangedEventHandler PropertyChanged;

    [XmlAttribute("Name")]
    [DataMember]
    public string Name
    {
        get { return _name; }
        set { 
            _name = value;
            OnPropertyChanged("Name");
            }
    }
    
    [DataMember]
    public int DeviceCount
    {
        get { return _deviceCount; }
        set { 
            _deviceCount = value; 
            OnPropertyChanged("DeviceCount");
            } 
    } 
    
    
    
    protected void OnPropertyChanged(string name)
    {
    PropertyChangedEventHandler handler = PropertyChanged;
    if (PropertyChanged != null)
        PropertyChanged(this, new PropertyChangedEventArgs(name));
    }
    

    }

【讨论】:

  • 我刚才在SubSystem上实现了INotifyPropertyChanged,把相关的调用放进去,但是运气不好,还是没有绑定,就像用户控件没有从UI上的数据绑定中获取值一样。令人沮丧的是,它在 UI 上放置了正确数量的控件。只是没有数据。
【解决方案3】:

在您的 SubSystem 类中,Name 属性应替换为 SystemName

[XmlAttribute("SystemName")]
[DataMember]
public string SystemName
{
    get { return _name; }
    set { _name = value; }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-20
    相关资源
    最近更新 更多