帮助一些非常基本的WPF数据绑定

时间:2022-08-24 13:38:52

I'm new to WPF and trying a simple example of databinding, but it's not working. My window has a TextBlock, which I bound to a property of the window object. I declared the property in code.

我是WPF的新手,并尝试了一个简单的数据绑定示例,但它不起作用。我的窗口有一个TextBlock,它绑定到window对象的一个​​属性。我在代码中声明了该属性。

When running this, I see the correct value appearing in the TextBlock. There's also a button, which when clicked updates the property, except I don't see this affecting the TextBlock.

运行此时,我看到TextBlock中出现正确的值。还有一个按钮,单击该按钮会更新属性,但我不会看到这会影响TextBlock。

I implemented the INotifyPropertyChanged correctly, as far as I'm able to determine. I also see, when debugging, that something has subscribed to the PropertyChanged event, except it doesn't seem to do anything.

我已经正确地实现了INotifyPropertyChanged,据我所知。我还看到,在调试时,有些东西订阅了PropertyChanged事件,除了它似乎没有做任何事情。

I have 2 questions:

我有两个问题:

1) Why isn't this working as expected?

1)为什么这不能按预期工作?

2) Is there any easy way to debug during run-time what's causing this, without resorting to third-party tools? From my cursory knowledge, it seems to me the debugging support in WPF is sorely lacking.

2)有没有简单的方法在运行时调试导致这种情况的原因,而不使用第三方工具?从我粗略的知识来看,在我看来,WPF中的调试支持非常缺乏。

The XAML is (not including the "standard" XAML window element):

XAML是(不包括“标准”XAML窗口元素):

<TextBlock Height="28" Name="label1" VerticalAlignment="Top"
       Text="{Binding Path=TheName}"
       Grid.Row="0"
       ></TextBlock>
<Button Height="23" Name="button1" VerticalAlignment="Stretch" Grid.Row="1"
Click="button1_Click">
    Button
</Button>

The code in the window class is:

窗口类中的代码是:

    public partial class Window1 : Window
    {
        protected MyDataSource TheSource { get; set; }

        public Window1()
        {
            InitializeComponent();
            TheSource = new MyDataSource();
            TheSource.TheName = "Original";  // This works
            this.label1.DataContext = this.TheSource;
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            TheSource.TheName = "Changed";  // This doesn't work
        }
    }
    public class MyDataSource : INotifyPropertyChanged
    {
        string thename;
        public string TheName 
        {
            get { return thename; }
            set { thename = value; OnPropertyChanged(thename); }
        }
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }
    }
}

3 个解决方案

#1


The problem is in you "TheName" property setter. The OnPropertyChanged method call is passing the value of "thename", not "the name" of "thename". (Sorry if that doesn't make sense - the variable names used for the example conspired against us!)

问题在于你的“TheName”属性设置器。 OnPropertyChanged方法调用传递“thename”的值,而不是“thename”的“名称”。 (对不起,如果这没有意义 - 用于示例的变量名称对我们密谋!)

The correct code would be:

正确的代码是:

string thename;
public string TheName 
{
  get { return thename; }
  set { thename = value; OnPropertyChanged("TheName"); }
}

Here is an example from MSDN.

以下是MSDN的示例。

Hope this helps!

希望这可以帮助!

#2


From Bea Stollnitz blog, here are a few ways to debug a WPF binding.

从Bea Stollnitz博客,这里有几种调试WPF绑定的方法。

  • Check the output window, as WPF logs alot of errors there

    检查输出窗口,因为WPF在那里记录了很多错误

  • You can add a Trace source to your app.config. Details on Mike Hillberg’s blog

    您可以将trace源添加到app.config中。有关Mike Hillberg博客的详细信息

  • Add a trace level to the binding (this is my favourite). Add the namespace xmlns:diagnostics="clr-namespace:System.Diagnostics;assembly=WindowsBase"
    and in your binding add the tracelevel
    <TextBlock Text="{Binding Path=TheName, diagnostics:PresentationTraceSources.TraceLevel=High}" />

    为绑定添加跟踪级别(这是我最喜欢的)。添加命名空间xmlns:diagnostics =“clr-namespace:System.Diagnostics; assembly = WindowsBase”并在绑定中添加tracelevel

  • Add a converter to your binding, and then put a breakpoint in the converter.

    将转换器添加到绑定中,然后在转换器中添加断点。

#3


Okay, thanks, I didn't pay enough attention when reading about the PropertyChangedEventArgs arguments. It seems like brittle design to rely on a string for the property name, but apparently other people think so too (from the link at the bottom of the user comments on that MSDN page you linked to).

好的,谢谢,我在阅读有关PropertyChangedEventArgs参数时没有给予足够的重视。似乎脆弱的设计依赖于字符串作为属性名称,但显然其他人也这么认为(从用户评论的底部链接到您链接到的MSDN页面)。

However, my second question is still unanswered: how could I debug this and find out what I did wrong?

但是,我的第二个问题仍然没有答案:我怎么能调试这个并找出我做错了什么?

For example, doesn't WPF log its actions in some form? It should notice that I do not have a property called "Changed" on this object, why doesn't it raise an exception or at least write something to the debug console?

例如,WPF不以某种形式记录其操作吗?它应该注意到我没有在这个对象上有一个名为“Changed”的属性,为什么不引发异常或者至少写一些东西到调试控制台?

#1


The problem is in you "TheName" property setter. The OnPropertyChanged method call is passing the value of "thename", not "the name" of "thename". (Sorry if that doesn't make sense - the variable names used for the example conspired against us!)

问题在于你的“TheName”属性设置器。 OnPropertyChanged方法调用传递“thename”的值,而不是“thename”的“名称”。 (对不起,如果这没有意义 - 用于示例的变量名称对我们密谋!)

The correct code would be:

正确的代码是:

string thename;
public string TheName 
{
  get { return thename; }
  set { thename = value; OnPropertyChanged("TheName"); }
}

Here is an example from MSDN.

以下是MSDN的示例。

Hope this helps!

希望这可以帮助!

#2


From Bea Stollnitz blog, here are a few ways to debug a WPF binding.

从Bea Stollnitz博客,这里有几种调试WPF绑定的方法。

  • Check the output window, as WPF logs alot of errors there

    检查输出窗口,因为WPF在那里记录了很多错误

  • You can add a Trace source to your app.config. Details on Mike Hillberg’s blog

    您可以将trace源添加到app.config中。有关Mike Hillberg博客的详细信息

  • Add a trace level to the binding (this is my favourite). Add the namespace xmlns:diagnostics="clr-namespace:System.Diagnostics;assembly=WindowsBase"
    and in your binding add the tracelevel
    <TextBlock Text="{Binding Path=TheName, diagnostics:PresentationTraceSources.TraceLevel=High}" />

    为绑定添加跟踪级别(这是我最喜欢的)。添加命名空间xmlns:diagnostics =“clr-namespace:System.Diagnostics; assembly = WindowsBase”并在绑定中添加tracelevel

  • Add a converter to your binding, and then put a breakpoint in the converter.

    将转换器添加到绑定中,然后在转换器中添加断点。

#3


Okay, thanks, I didn't pay enough attention when reading about the PropertyChangedEventArgs arguments. It seems like brittle design to rely on a string for the property name, but apparently other people think so too (from the link at the bottom of the user comments on that MSDN page you linked to).

好的,谢谢,我在阅读有关PropertyChangedEventArgs参数时没有给予足够的重视。似乎脆弱的设计依赖于字符串作为属性名称,但显然其他人也这么认为(从用户评论的底部链接到您链接到的MSDN页面)。

However, my second question is still unanswered: how could I debug this and find out what I did wrong?

但是,我的第二个问题仍然没有答案:我怎么能调试这个并找出我做错了什么?

For example, doesn't WPF log its actions in some form? It should notice that I do not have a property called "Changed" on this object, why doesn't it raise an exception or at least write something to the debug console?

例如,WPF不以某种形式记录其操作吗?它应该注意到我没有在这个对象上有一个名为“Changed”的属性,为什么不引发异常或者至少写一些东西到调试控制台?