绑定的文本框值未更新 [英] Bound textbox value not updated
问题描述
大家好,
我一直在寻找过去几周的教程(在过去的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屋!