WPF 与 INotifyPropertyChanged 的​​绑定不会更新

发布于 2024-09-06 20:43:54 字数 2552 浏览 1 评论 0原文

当我更新 WPF UI 所绑定的属性时,我似乎遇到了严重的问题。这是我的视图模型类定义:

namespace WpfModel
    {
        class AppModel : INotifyPropertyChanged
        {
            private int _count = 7;

        public int Count { get { return _count; } 
        set { _count = value;     OnPropertyChanged("Count"); } }

        public void Increment()
        {
            Count++;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string prop)
        {
            PropertyChangedEventHandler handler = this.PropertyChanged;

            if (handler != null)
            {
                var e = new PropertyChangedEventArgs("prop");
                handler(this, e);
            }
        }
    };
}

这在以下 XAML 中绑定到我的简单 UI:

<Window x:Class="WpfModel.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="clr-namespace:WpfModel"
        Title="WPF Data Model Demo" Height="128" Width="284" >

    <Window.DataContext>
        <vm:AppModel />
    </Window.DataContext>

    <Grid Height="Auto" Width="Auto">
        <Button Margin="0,0,12,12" Name="IncButton" Height="23" VerticalAlignment="Bottom" HorizontalAlignment="Right" Width="75" Click="IncButton_Click" Content="Increment" />
        <Label Content="Count Variable:" Height="28" HorizontalAlignment="Left" Margin="12,12,0,0" Name="label1" VerticalAlignment="Top" />
        <Label Height="28" Margin="116,12,0,0" Name="CountLabel" VerticalAlignment="Top" HorizontalAlignment="Left" Width="40" Content="{Binding Path=Count}" />
    </Grid>
</Window>

应用程序定义如下:

namespace WpfModel
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private AppModel _model = new AppModel();

        public MainWindow()
        {
            InitializeComponent();

            //_model = new AppModel();
        }

        private void IncButton_Click(object sender, RoutedEventArgs e)
        {
        }
    }
}

当应用程序启动时,一切都很好,标签甚至最初显示 Count 属性中的任何值模型。调用increment会正确更新模型,并且直接增加Count属性(如代码所示)也可以正常工作。

这里的问题是,PropertyChanged 事件处理程序似乎永远不会被添加到。我可以单步执行调试器中的代码并查看属性更新中的值,甚至可以看到对 OnPropertyChanged 的​​调用,但 PropertyChanged 处理程序本身始终为 null。

是不是我的绑定有问题?

我正在使用 MSVC 2010 Express。

I appear to be having serious problems getting my WPF UI to update when I update when I update the property it is bound to. Here is my view model class definition:

namespace WpfModel
    {
        class AppModel : INotifyPropertyChanged
        {
            private int _count = 7;

        public int Count { get { return _count; } 
        set { _count = value;     OnPropertyChanged("Count"); } }

        public void Increment()
        {
            Count++;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string prop)
        {
            PropertyChangedEventHandler handler = this.PropertyChanged;

            if (handler != null)
            {
                var e = new PropertyChangedEventArgs("prop");
                handler(this, e);
            }
        }
    };
}

This is bound to my simple UI in the following XAML:

<Window x:Class="WpfModel.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="clr-namespace:WpfModel"
        Title="WPF Data Model Demo" Height="128" Width="284" >

    <Window.DataContext>
        <vm:AppModel />
    </Window.DataContext>

    <Grid Height="Auto" Width="Auto">
        <Button Margin="0,0,12,12" Name="IncButton" Height="23" VerticalAlignment="Bottom" HorizontalAlignment="Right" Width="75" Click="IncButton_Click" Content="Increment" />
        <Label Content="Count Variable:" Height="28" HorizontalAlignment="Left" Margin="12,12,0,0" Name="label1" VerticalAlignment="Top" />
        <Label Height="28" Margin="116,12,0,0" Name="CountLabel" VerticalAlignment="Top" HorizontalAlignment="Left" Width="40" Content="{Binding Path=Count}" />
    </Grid>
</Window>

The application is defined like follows:

namespace WpfModel
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private AppModel _model = new AppModel();

        public MainWindow()
        {
            InitializeComponent();

            //_model = new AppModel();
        }

        private void IncButton_Click(object sender, RoutedEventArgs e)
        {
        }
    }
}

When the app starts up, everything is peachy, the label even initially displays whatever value is in the Count property of the model. Calling increment updates the model properly, and directly incrementing the Count property as shown in the code also works just fine.

The problem here, is that the PropertyChanged event handler never seems to get added to. I can step through the code in the debugger and see the value in the property updating, and I can see the call to OnPropertyChanged even, but the PropertyChanged handler itself is always null.

Is there a problem with my binding maybe?

I am using MSVC 2010 Express.

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

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

发布评论

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

评论(2

鸠魁 2024-09-13 20:43:54

问题是,作为实例变量 _model 的 WpfModel 与用作窗口 DataContext 的实例不同。因此,它不受任何东西的约束,并且它的 PropertyChanged 将始终为 null。

将用于设置数据上下文的 XAML 更改为以下内容:

<Window.DataContext>
            <vm:AppModel x:Name="_model" />
</Window.DataContext>

去掉后面代码中声明的实例变量,并修复 OnPropertyChanged 实现(使用参数而不是文字字符串“prop”),并且它可以工作。

The issue is that the WpfModel you have as an instance variable, _model, is not the same instance that's being used as the Window's DataContext. Thus, it is not bound to by anything, and its PropertyChanged will always be null.

Change your XAML for setting the datacontext to this:

<Window.DataContext>
            <vm:AppModel x:Name="_model" />
</Window.DataContext>

Get rid of the instance variable declared in the code behind, and fix the OnPropertyChanged implementation (use the parameter instead of the literal string "prop"), and it works.

衣神在巴黎 2024-09-13 20:43:54

这一行:

var e = new PropertyChangedEventArgs("prop");

应该是:

var e = new PropertyChangedEventArgs(prop);

您正在传递字符串“prop”,因此不会触发侦听“Count”的绑定值。

**编辑 **
根据您的其他评论(答案?)我认为我最好通过修复来更新它 - 您当然可以使用已经给出的答案,但我不想复制其他人:)。

将其添加到您的点击处理程序中:

((AppModel)this.DataContext).Count += 1;

this line:

var e = new PropertyChangedEventArgs("prop");

should be:

var e = new PropertyChangedEventArgs(prop);

You are passing the string "prop" so the bound values listening for "Count" will not be triggered.

**EDIT **
Based on your other comments (Answer?) I thought I had better update this with a fix - you could use the answer already given of course but I dont want to copy someone else :).

Add this to your click handler:

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