Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/299.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用UpdateSourceTrigger=PropertyChanged更新WPF时出现问题_C#_.net_Wpf_Xaml - Fatal编程技术网

C# 使用UpdateSourceTrigger=PropertyChanged更新WPF时出现问题

C# 使用UpdateSourceTrigger=PropertyChanged更新WPF时出现问题,c#,.net,wpf,xaml,C#,.net,Wpf,Xaml,首先(完全公开),我是C#的相对初学者,所以这可能是一个明显的oops。我已经在stackoverflow上复习了几十个类似的问题和例子,但我仍然无法找出我做错了什么。我从VS 2017 WPFapp项目开始。更改了启动,以便我可以手动加载窗口。创建了一个带有递增值计时器的类,然后使用INotifyPropertyChanged更新我的主窗口上的文本框 WPF窗口加载良好。TextBlock以值5开始,因此绑定至少指向我的类和值。您将在输出中注意到,值正在随计时器事件更新,NotifyPrope

首先(完全公开),我是C#的相对初学者,所以这可能是一个明显的oops。我已经在stackoverflow上复习了几十个类似的问题和例子,但我仍然无法找出我做错了什么。我从VS 2017 WPFapp项目开始。更改了启动,以便我可以手动加载窗口。创建了一个带有递增值计时器的类,然后使用INotifyPropertyChanged更新我的主窗口上的文本框

WPF窗口加载良好。TextBlock以值5开始,因此绑定至少指向我的类和值。您将在输出中注意到,值正在随计时器事件更新,NotifyPropertyChanged正在触发,但TextBlock从未更改

我唯一的想法是TextBlock链接到了我的UpdateWPF类的错误实例,但我不明白这是怎么回事

提前感谢您的帮助

这是我的密码

MainWindow.xaml:(实际上刚刚删除了一个文本块并设置了绑定)

App.xaml(刚刚注释掉了StartupUri)

和输出

Timer Event Fired. New Value is 6 
NotifyPropertyChanged Fired. 
Timer Event Fired. New Value is 7 
NotifyPropertyChanged Fired. 
Timer Event Fired. New Value is 8 
NotifyPropertyChanged Fired. 
Timer Event Fired. New Value is 9 
NotifyPropertyChanged Fired. 
Timer Event Fired. New Value is 10 
NotifyPropertyChanged Fired. 
Timer Event Fired. New Value is 11 
NotifyPropertyChanged Fired.

正如上面的评论中所说,您必须正确设置
UpdateSourceTrigger
。我也不推荐您实现属性的方式。它们应该是这样的:

private int _value;

public int Value
{
    get => _value;
    set
    {
        _value = value;
        OnPropertyChanged(nameof(Value));
    }
}
现在你可以说
Value=0
而不是手动引发
属性更改
事件

如果将
NotifyPropertyChanged
方法更改为:

private void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgw(propertyName));
            Console.WriteLine("NotifyPropertyChanged Fired.");
}
您不必将属性名称传递给
NotifyPropertyChanged
。运行时将自动执行此操作,因为调用了
CallerMemberNameAttribute

问候

洛里斯

编辑:

我的财产只是一个财产的例子,而不是你的。但是你只要改变类型,它就会工作

这应该适合您:

public class UpdateWPF : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            Console.WriteLine("NotifyPropertyChanged Fired.");
        }

        private int _value = 5;

        public UpdateWPF()
        {
            Timer aTimer = new System.Timers.Timer();
            aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
            aTimer.Interval = 1000;
            aTimer.Enabled = true;
        }
        private void OnTimedEvent(object source, ElapsedEventArgs e)
        {
            var i = Convert.ToInt32(value);
            Value = ++i;
        }
        public string Value
        {
            get => _value;
            set
            {
                _value = value;
                NotifyPropertyChanged();
            }
        }
    }

正如上面的评论中所说,您必须正确设置
UpdateSourceTrigger
。我也不推荐您实现属性的方式。它们应该是这样的:

private int _value;

public int Value
{
    get => _value;
    set
    {
        _value = value;
        OnPropertyChanged(nameof(Value));
    }
}
现在你可以说
Value=0
而不是手动引发
属性更改
事件

如果将
NotifyPropertyChanged
方法更改为:

private void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgw(propertyName));
            Console.WriteLine("NotifyPropertyChanged Fired.");
}
您不必将属性名称传递给
NotifyPropertyChanged
。运行时将自动执行此操作,因为调用了
CallerMemberNameAttribute

问候

洛里斯

编辑:

我的财产只是一个财产的例子,而不是你的。但是你只要改变类型,它就会工作

这应该适合您:

public class UpdateWPF : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            Console.WriteLine("NotifyPropertyChanged Fired.");
        }

        private int _value = 5;

        public UpdateWPF()
        {
            Timer aTimer = new System.Timers.Timer();
            aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
            aTimer.Interval = 1000;
            aTimer.Enabled = true;
        }
        private void OnTimedEvent(object source, ElapsedEventArgs e)
        {
            var i = Convert.ToInt32(value);
            Value = ++i;
        }
        public string Value
        {
            get => _value;
            set
            {
                _value = value;
                NotifyPropertyChanged();
            }
        }
    }

ASh发现了我的问题,但他将其作为评论发布,所以我将回答这个问题。因为我已经解决了其他一些问题,所以我把它们都贴在这里

真正的问题出现在我的主窗口中。xaml

Text="{Binding Path=GetValue,Mode=OneTime,UpdateSourceTrigger=PropertyChanged}"
应该是

Text="{Binding Path=GetValue,Mode=OneWay}"
以后会变成

Text="{Binding Path=Value,Mode=OneWay}"
正如ASh指出的,UpdateSourceTrigger在本例中完全没有意义

Loris156指出了一些其他问题。有些建议是错误的,但我无意中发现了其中的优点,并得出了结论

命名约定

我来自java,所有的东西都在获取这个或设置这个,这个是变量。
MS建议Value(){get;set;},Value为变量。loris156更喜欢_值,我看到很多人都这么做。碰巧“value”是一个非常糟糕的例子,因为它在自动属性设置器中使用。尽管如此,我还是坚持MS的方式,因为我使用的是他们的编译器

因此,我的getter/setter变成了“Value”

我还要指出,Lori156使用了int返回,但这对我使用的文本框不起作用

我以前无法使[CallerMemberName]正常工作。这也与我的能手/二传手有关。通过排除setter,我破坏了auto属性功能。看

正如我前面提到的,int getter不能使用文本框,所以我选择在setter中将字符串转换回int。这真的没关系,反正我也不会用。 下面是App.xaml.cs的代码更改

private void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            Console.WriteLine("NotifyPropertyChanged Fired.");
        }


如果有人有进一步的建议,我愿意接受

ASh发现了我的问题,但他将其作为评论发布,所以我将回答这个问题。因为我已经解决了其他一些问题,所以我把它们都贴在这里

真正的问题出现在我的主窗口中。xaml

Text="{Binding Path=GetValue,Mode=OneTime,UpdateSourceTrigger=PropertyChanged}"
应该是

Text="{Binding Path=GetValue,Mode=OneWay}"
以后会变成

Text="{Binding Path=Value,Mode=OneWay}"
正如ASh指出的,UpdateSourceTrigger在本例中完全没有意义

Loris156指出了一些其他问题。有些建议是错误的,但我无意中发现了其中的优点,并得出了结论

命名约定

我来自java,所有的东西都在获取这个或设置这个,这个是变量。
MS建议Value(){get;set;},Value为变量。loris156更喜欢_值,我看到很多人都这么做。碰巧“value”是一个非常糟糕的例子,因为它在自动属性设置器中使用。尽管如此,我还是坚持MS的方式,因为我使用的是他们的编译器

因此,我的getter/setter变成了“Value”

我还要指出,Lori156使用了int返回,但这对我使用的文本框不起作用

我以前无法使[CallerMemberName]正常工作。这也与我的能手/二传手有关。通过排除setter,我破坏了auto属性功能。看

正如我前面提到的,int getter不能使用文本框,所以我选择在setter中将字符串转换回int。这真的没关系,反正我也不会用。 下面是App.xaml.cs的代码更改

private void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            Console.WriteLine("NotifyPropertyChanged Fired.");
        }

我开着