【问题标题】:WPF two way mode binding using INotifyPropertyChanged not working使用 INotifyPropertyChanged 的​​ WPF 双向模式绑定不起作用
【发布时间】:2016-05-18 19:05:45
【问题描述】:

所以我面临一个棘手的问题。这是我的视图模型:

namespace Market.ViewModel
{
    public class BillingViewModel : ViewModelBase
    {
        #region Private Members

        private Customer _customer;
        private Product _products;
        private string _productId = "asd";
        RelayCommand _numClickedCommand;

        #endregion

        public Customer Customer
        {
            get { return _customer; }
            set
            {
                _customer = value;
                NotifyPropertyChanged("Customer");
            }
        }

        public Product Products
        {
            get { return _products; }
            set
            {
                _products = value;
                NotifyPropertyChanged("Products");
            }
        }

        public bool CanClick
        {
            get { return true; }
        }

        public string ProductId
        {
            get { return _productId; }
            set
            {
                _productId = value;
                NotifyPropertyChanged("ProductId");
            }
        }

        public ICommand NumClickedCommand
        {
            get
            {
                if (_numClickedCommand == null)
                {
                    _numClickedCommand = new RelayCommand(param => this.NumClicked(param.ToString()),
                        param => this.CanClick);
                }
                return _numClickedCommand;
            }
        }

        #region PrivateMethods

        private void NumClicked(string numClicked)
        {
            ProductId = ProductId+numClicked;
        }

        #endregion
    }
}

它继承了实现 INotifyPropertyCanged 的​​ ViewModelBase。

public class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

而我的看法是:

<Window x:Class="Billing.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:controls="clr-namespace:Billing"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:viewModel="clr-namespace:Market.ViewModel;assembly=Market.ViewModel"
    xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
    Title="MainWindow" Height="350" Width="525">

    <Window.Resources>
        <viewModel:BillingViewModel x:Key="ViewModel" />
    </Window.Resources>
    <Grid DataContext="{Binding Source={StaticResource ViewModel}}">
        <controls:NumPad HorizontalAlignment="Left" Margin="265,205,0,-192" VerticalAlignment="Top" Height="307" Width="242"/>
        <TextBox HorizontalAlignment="Left" Height="23" Margin="247,29,0,0" TextWrapping="Wrap" Text="{Binding ProductId, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" Width="120"/>
    </Grid>
</Window>

在这个 xaml 中使用了 NumClickedCommand:

<UserControl x:Class="Billing.NumPad"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:viewModel="clr-namespace:Market.ViewModel;assembly=Market.ViewModel"
         mc:Ignorable="d" Height="109" Width="248">

    <UserControl.Resources>
        <viewModel:BillingViewModel x:Key="ViewModel"/>
    </UserControl.Resources>
    <Grid Height="109" VerticalAlignment="Top" DataContext="{Binding Source={StaticResource ViewModel}}">
        <Button Content="1" HorizontalAlignment="Left" Margin="10,0,0,0" VerticalAlignment="Top" Width="75" CommandParameter="1" Command="{Binding NumClickedCommand}"/>
        <Button Content="2" HorizontalAlignment="Left" Margin="90,0,0,0" VerticalAlignment="Top" Width="75" CommandParameter="2" Command="{Binding NumClickedCommand}"/>
        <Button Content="3" HorizontalAlignment="Left" Margin="170,0,0,0" VerticalAlignment="Top" Width="75" CommandParameter="3" Command="{Binding NumClickedCommand}"/>
        <Button Content="4" HorizontalAlignment="Left" Margin="10,27,0,0" VerticalAlignment="Top" Width="75" CommandParameter="4" Command="{Binding NumClickedCommand}"/>
        <Button Content="5" HorizontalAlignment="Left" Margin="90,27,0,0" VerticalAlignment="Top" Width="75" CommandParameter="5" Command="{Binding NumClickedCommand}"/>
        <Button Content="6" HorizontalAlignment="Left" Margin="170,27,0,0" VerticalAlignment="Top" Width="75" RenderTransformOrigin="1.034,2.171" CommandParameter="6" Command="{Binding NumClickedCommand}"/>
        <Button Content="7" HorizontalAlignment="Left" Margin="10,54,0,0" VerticalAlignment="Top" Width="75" CommandParameter="7" Command="{Binding NumClickedCommand}"/>
        <Button Content="8" HorizontalAlignment="Left" Margin="90,54,0,0" VerticalAlignment="Top" Width="75" CommandParameter="8" Command="{Binding NumClickedCommand}"/>
        <Button Content="9" HorizontalAlignment="Left" Margin="170,54,0,0" VerticalAlignment="Top" Width="75" CommandParameter="9" Command="{Binding NumClickedCommand}"/>
        <Button Content="0" HorizontalAlignment="Left" Margin="10,81,0,0" VerticalAlignment="Top" Width="75"  CommandParameter="0" Command="{Binding NumClickedCommand}"/>
        <Button Content="Submit" HorizontalAlignment="Left" Margin="90,81,0,0" VerticalAlignment="Top" Width="155" />

    </Grid>
</UserControl>

问题是在视图模型中更新 ProductId 不会反映在视图中。 asd 的初始值在应用程序启动时更新。这些控件包含一组实现 ICommand 接口的按钮,它们都调用 viewmodel 中的 NumClicked()。在调试时,如果我单击按钮 NumClicked() 被调用,则 ProductId 被更新并且 NotifyPropertyChanged() 也被调用但 UI 没有更新,它保持不变。但是如果我直接更新 UI,即我在文本框中输入一些值,就会发生相同的流程,PropertyChanged() 会被调用,之后还会调用 get 来更新 viewmodel 中的值。

我已经解决了许多这样的问题,但无法弄清楚究竟是什么阻止了 UI 的更新。任何帮助表示赞赏,并询问是否缺少任何东西。 谢谢。

【问题讨论】:

  • NumClickedCommand 在哪里使用?
  • 我认为你的问题是 NumClickedCommand 而不是 ProductId 的更新
  • 我没有得到你,没有更新 ProductId?每次单击按钮时都会更新 ProductId

标签: c# wpf mvvm data-binding inotifypropertychanged


【解决方案1】:

GridTextBox 中的DataContext 绑定到来自 Window 资源的视图模型实例。

NumPad 控件声明自己的视图模型实例

NumClickedCommand 使用错误的数据,而不是显示的对象

确保您只有一个视图模型实例

NumPad 继承 DataContext 并且不应创建新对象并更改 DataContext

<UserControl x:Class="Billing.NumPad"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:viewModel="clr-namespace:Market.ViewModel;assembly=Market.ViewModel"
         mc:Ignorable="d" Height="109" Width="248">

<Grid Height="109" VerticalAlignment="Top">
    <!--all Buttons here-->    
</Grid>

【讨论】:

    【解决方案2】:

    您将相同的视图模型传递给 numpadUser 控件和主窗口也作为 DataContext,这样将创建视图模型的新实例,因此根据我的说法,您可以在 NumPad 中使用主窗口的 DataContext,也可以使用 Minwindow 的 GridName,您必须将网格命名为

    <Grid DataContext="{Binding Source={StaticResource ViewModel}}" x:Name="grdNumPad">
    

    您可以通过这种方式在 NumPad.XAML 中访问该 DataContext

    <Button Content="1" HorizontalAlignment="Left" Margin="10,0,0,0" VerticalAlignment="Top" Width="75" CommandParameter="1" Command="{Binding DataContext.NumClickedCommand,ElementName=grdNumPad}"/>
    

    【讨论】:

      猜你喜欢
      • 2014-04-10
      • 2011-10-14
      • 2011-09-17
      • 1970-01-01
      • 2019-11-13
      • 1970-01-01
      • 2012-02-14
      相关资源
      最近更新 更多