绑定的文本框值未更新 [英] Bound textbox value not updated

查看:64
本文介绍了绑定的文本框值未更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好,



我一直在寻找过去几周的教程(在过去的3天里更加强烈)关于使用mvvm方法的WPF并且遗漏了一些我不确定的东西。切入追逐,我已经创建了一个包含MainWindow的4个类的测试应用程序(在本教程中,我通过合并模型和视图模型类而故意违反了MVVM原则,因此我可以更快地浏览我的代码,而无需使用太多选项卡视觉工作室)



所以这里是我的模型和视图模型类,它继承自ObservableObject类

Hi everyone,

I've been looking up tutorials for the past few weeks (and even more intensely during the past 3 days) about WPF with mvvm approach and have been missing something which I am not sure of. Cutting to the chase, I have created a test application with 4 classes including the MainWindow (during this tutorial I have purpossedly violated the MVVM principle by merging the model and view model classes just so I can browse my code quicker without having too many tabs in visual studio)

so here's my model and view model class which inherits from ObservableObject class

string _partnumber
int _price
Part _currpart

public string PartNumber
{
     get {return _partnumber;}
     set
      {
          if (value != _partnumber)
          {
              _partnumber = value;
              OnPropertyChanged("PartNumber");
          }
      }
}

//I also have 2 other properties which is written the same way so I'll just keep it short

public int Price
{
   //the usual get, written the same way as PartNumber property
     set
       {
          //just like PartNmber, checks for value and then set it
          OnPropertyChanged("Price");
       }
}

public Part CurrentPart
{
     //the usual get, written the same way as PartNumber property
     set
       {
          //just like PartNmber, checks for value and then set it
          OnPropertyChanged("Part");
       }
}

private ICommand _getpricecommand;

public ICommand GetPriceCommand
 {
            get
            {
                if (_getpricecommand == null)
                {
                    _getpricecommand = new RelayCommand(param => GetPrice(),param => true);
                }
                return _getpricecommand;
            }
}

private void GetPrice()
{
            Part p = new Part();
            p.PartNumber = "6H-4130-01";
            p.price = 7;
            CurrentPart = p;
}





ObservableObject类



ObservableObject class

public event PropertyChangedEventHandler PropertyChanged;
        
        protected virtual void OnPropertyChanged(string PropertyName)
        {
            PropertyChangedEventHandler hndl = this.PropertyChanged;
            if (hndl != null)
            {
                var e = new PropertyChangedEventArgs(PropertyName);
                hndl(this, e);
            }
        }

        public virtual void RaisePropertyChanged(string PropertyName)
        {
            OnPropertyChanged(PropertyName);
        }





最后,RelayCommand类



and finally, RelayCommand class

readonly Action<object> _execute;
readonly Predicate<object> _canexecute;

public RelayCommand(Action<object> Execute ) : this(Execute,null)
{

}

public RelayCommand(Action<object> Execute, Predicate<object> CanExecute)
{
    if(Execute == null)
    {
        throw new ArgumentNullException("execute");
    }
    _execute = Execute;
    _canexecute = CanExecute;

}

public event EventHandler CanExecuteChanged
{
    add { CommandManager.RequerySuggested += value; }
    remove { CommandManager.RequerySuggested -= value; }
}

[DebuggerStepThrough]
public bool CanExecute(object parameter)
{
    return _canexecute == null ? true : _canexecute(parameter);
}

public void Execute(object parameter)
{
    _execute(parameter);
}





视图,也就是MainWindow,我用以下方式覆盖OnStartUp:



for the view, which is the MainWindow, I override the OnStartUp with:

MainWindow app = new MainWindow();
Part p = new Part();
app.DataContext = p;
app.Show();





最后



and finally

<Window.Resources>
    <DataTemplate DataType="local:Part" />
</Window.Resources>

<StackPanel DataContext="{Binding CurrentPart}">
            <TextBlock Text="{Binding PartNumber}" Height="50" Width="150" />
            <TextBlock Text="{Binding Price}" Height="50" Width="150" />
            <Button Command="{Binding GetPriceCommand}" Height="50" Width="150" Content="Get Part" />
        </StackPanel>





因此,在按下获取零件按钮时,它应显示顶部文本框和价格中的零件号在底部文本框中,但没有任何显示。我在GetPrice()和GetPriceCommand中放置了断点,但它们似乎按原样传递属性。我错过了什么?



So at the press of Get Part button, it should display the partnumber in the top textbox and price in bottom textbox, but nothing showed up. I placed breakpoints in GetPrice() and GetPriceCommand but they seem to pass on the properties as they should. What did I miss?

推荐答案

在xaml中做这样的事情

In the xaml do something like this

<window x:class="TestBindings.MainWindow" xmlns:x="#unknown">
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:TestBindings"
        Title="MainWindow" >
    <window.datacontext>
        <local:testbindingsvm xmlns:local="#unknown" />
    </window.datacontext>

    <grid>
    .......
      <textbox text="{Binding PartNumber}" .....="" />
         ..............
  
      <textbox text="{Binding Price}" ......="" />
        ..............................
      <button command="{Binding GetPriceCommand}" content="Get Part" />
       .................
    </grid>
</window>

在视图模型的构造函数中,实例化 Part 类。

In the view model's constructor, instantiate the Part class.

namespace TestBindings
{
    using System.Windows.Input;

 public class TestBindingsVM : ViewModelBase
    {
        #region Constants and Fields

        private readonly Part model;

        #endregion

        #region Constructors and Destructors

        public TestBindingsVM()
        {
            this.model = new Part();
           .....
        }
//declare your properties like this

  public int Price
        {
            get
            {
                return this.model.Price;
            }
            set
            {
                if (value != this.model.Price)
                {
                    this.model.Price = value;
                    this.RaisePropertyChanged();
                }
            }
        }
 // This is the ViewModelBase class

    using System.ComponentModel;
    using System.Runtime.CompilerServices;

    public abstract class ViewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected void RaisePropertyChanged([CallerMemberName] string caller = "")
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(caller));
            }
        }

    }


问题出在Set PartNumber属性中。 Set PartNumber也应该调用OnPropertyChanged(Price)。这样,当在文本框中更新PartNumber时,价格也会同时更新。



在这种情况下也不需要CurrPart。



PartNumber应如下所示



The problem lies in the Set PartNumber property. Set PartNumber should also call for OnPropertyChanged("Price"). This way, when PartNumber is updated in the text box, the Price is also updated at the same time.

CurrPart is also not required in this case.

PartNumber should look like this

public string PartNumber
{
     get {return _partnumber;}
     set
       {
           if (_partnumber != value)
             {
                  _partnumber = value;
                  OnPropertyChanged("PartNumber");
                  OnPropertyChanged("Price");
             }
}





接下来做的是更改GetPrice()。如前所述,不再需要CurrPart,因此更新_partnumber和_price应该可以解决问题。





Next to do is to change the GetPrice(). As said before, CurrPart is no longer necessary, so updating the _partnumber and _price should do the trick.

private void GetPrice()
{
     _partnumber = /*part number value*/;
     _price = /*set price value*/;
}


这篇关于绑定的文本框值未更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆