UserControl 到 ObservableCollection 的 DataBinding Text 属性不更新

发布于 2024-12-01 10:46:45 字数 1044 浏览 1 评论 0原文

我创建了一个 UserControl,它是根据绑定的 ObservableCollection 的内容显示转换后的字符串值。当应用程序加载时,一切正常;我的 IValueConverter 被调用并产生正确的字符串结果,该结果在我的 UserControl 中正确显示。但是,如果 ObservableCollection 内容发生更改,我的控件不会更新。

另外,在创建此控件之前,我有相同的行为,但绑定了常规 Button 控件的 Content 属性,并且这也可以正常工作并按预期更新。

我想通过我的用户控件获得同样的东西,我缺少什么想法吗?

控制属性看起来像;

public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register("Text", typeof(string), typeof(MyUserControl));

public string Text
{
    get { return GetValue(TextProperty) as string; }
    set { SetValue(TextProperty, value);
}

UserControl XAML 中的相关部分(显示转换后的字符串值)是:

<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type Controls:MyUserControl}}, Path=Text}" />

并且该控件是在单独的窗口中创建的,如下所示;

<CoreControls:MyUserControl 
    Name="myControl" 
    Text="{Binding Path=ObservableCollectionInstance, Converter={StaticResource MyValueConverter}, Mode=OneWay}" />

I have created a UserControl, which is to display a converted string value based on the contents of a bound ObservableCollection. Everything works when the application loads; my IValueConverter is called and produces the correct string result, which is displayed correctly in my UserControl. However if the ObservableCollection contents change, my control is not updated.

Also, before I created this control, I had the same behaviour, but binding the Content property of a regular Button control, and this also worked correctly and updated as expected.

Any ideas what I am missing to get the same thing with my UserControl?

The control property looks like;

public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register("Text", typeof(string), typeof(MyUserControl));

public string Text
{
    get { return GetValue(TextProperty) as string; }
    set { SetValue(TextProperty, value);
}

The relevant section in the UserControl XAML (which displays the converted string value) is;

<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type Controls:MyUserControl}}, Path=Text}" />

And the control is created in a separate Window like so;

<CoreControls:MyUserControl 
    Name="myControl" 
    Text="{Binding Path=ObservableCollectionInstance, Converter={StaticResource MyValueConverter}, Mode=OneWay}" />

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

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

发布评论

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

评论(3

遥远的她 2024-12-08 10:46:45

我会在绑定中使用 ElementName 而不是 RelativeSource,因为您已经命名了用户控件。另外,您正在尝试将集合绑定到 旨在显示单个项目。这可能就是它不起作用的原因。 ObservableCollection 触发 CollectionChanged 事件,而不是 PropertyChanged。即使它确实响应,您仍然会遇到问题,因为 ObservableCollection 不会在其中包含的项目发生属性更改时发出通知 - 仅当添加/删除项目等时(想想,集合本身发生变化)。如果这是您想要的行为,您将必须编写一些代码。

编辑
在您发表评论后,在我看来,即使您将其设置为 OneWay 绑定模式,其行为也类似于 OneTime 绑定模式。
我会尝试这样做来帮助您调试它:

添加此 xmlns:

xmlns:diagnostics="clr-namespace:System.Diagnostics;assembly=WindowsBase"

然后在您的绑定中添加此:

diagnostics:PresentationTraceSources.TraceLevel=High

这是一篇关于调试绑定的文章

您可以做的另一件事是在转换器中设置断点。当您向收藏中添加/删除内容时,看看它是否真的在更新。我愿意打赌,它的 bc ObservableCollection 不会触发 PropertyChanged 事件,并且初始更新会发生,因为它不是基于更新事件。

I would use ElementName instead of RelativeSource in your binding, since you have named your user control. Also, you are trying to bind a collection to a <Textbox>. a <Textbox> is designed to display a single item. this is probably why its not working. ObservableCollection fires CollectionChanged events, not PropertyChanged. Even if it did respond, you are still going to have problems because ObservableCollection does not notify when an item contained in it has property changes--only when items are added/removed etc (think, the collection itself changes). If this is the behavior you want, you are going to have to write some code.

EDIT
after your comments, it sounds to me like even though you set it to OneWay binding mode, its acting like OneTime binding mode.
I would try this to help you debug it:

add this xmlns:

xmlns:diagnostics="clr-namespace:System.Diagnostics;assembly=WindowsBase"

and then, in your binding add this:

diagnostics:PresentationTraceSources.TraceLevel=High

here is an article on debugging bindings.

the other thing you could do is set breakpoints in your converter. see if its actually updating when you add/remove things to your collection. I would be willing to bet that its bc the ObservableCollection is NOT firing PropertyChanged events and that the initial update occurs because its not based on an update event.

守不住的情 2024-12-08 10:46:45

ObservableCollection 仅在添加或删除项目时发出通知。它用于观察集合。它们更适合内容控制。请此处阅读相关内容。您正在谈论观察一个属性,这需要 INotifyPropertyChanged 。发布更多代码可能会有所帮助,例如您如何更改集合的值。

ObservableCollection notifies only in case if items get added or removed. It is used to observe a collection. They are more suited for content controls. Read about it here. You are talking about observing a property, which needs INotifyPropertyChanged. Posting more code might help, like how are you changing the value of the collection.

只有一腔孤勇 2024-12-08 10:46:45

谢谢你们的提示。

我设法找到了一个解决方案;我可以处理 ObservableCollection 上的 CollectionChanged 事件,然后使用类似的内容显式更新目标;

BindingExpression exp = myControl.GetBindingExpression(MyUserControl.TextProperty);
if (null != exp) exp.UpdateTarget();

如前所述,最有可能的是,对 Text 属性的绑定仅侦听 PropertyChanged 事件,而不是 NotifyCollectionChanged 事件,但此解决方案可以解决问题。

Thanks for the tips guys.

I managed to work out a solution; I can handle the CollectionChanged event on the ObservableCollection and then explicitly update the target with something like;

BindingExpression exp = myControl.GetBindingExpression(MyUserControl.TextProperty);
if (null != exp) exp.UpdateTarget();

As noted, most likely, binding on the Text property is only listening to PropertyChanged events, not NotifyCollectionChanged events, but this solution does the trick.

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