May*_*aya 6 data-binding wpf mvvm updatesourcetrigger showdialog
我看到了这个例子--Binding.UpdateSourceTrigger属性
在示例中,UpdateSourceTrigger设置为Explicit,然后在视图代码中调用TextBox名称的UpdateSource.
但是,如果我使用MVVM dp,我不想让我的控件和源属性在VM中,而不是在视图中,那么将控件绑定到VM属性并将UpdateSourceTrigger设置为显式的正确方法是什么?
我想这样做,因为在我的情况下它的ShowDialog窗口,我希望只有当用户点击"确定"时源才会更新
提前致谢!
WPF*_*-it 12
如果你真的使用MVVM,那么你的OK按钮必须由一些人来处理Command.此命令必须来自您的ViewModel.该Expliticly绑定属性必须从现身ViewModel一次.所以什么阻止你.
Explicit绑定但使用OneWay绑定.OneWay绑定的Dependency属性.NotifyPropertyChanged从你的房子那里筹集房产ViewModel.例如
假设我需要在单击确定按钮时将TextBox的文本更新回我的模型.
所以为此,我有一个EmployeeViewModel具有EmployeeName属性的类.该物业有一个吸气剂和一个二传手.setter引发属性更改通知.视图模型也有类型的另一个属性ICommand名为SaveNameCommand返回给我执行命令.
EmployeeViewModel是我的视图的数据上下文类型.MyView的有TextBox(命名为x:名称="EmployeeNameTxBx")OneWay绑定到EmployeeName和一个按钮OK.我将Button.Command属性绑定到EmployeeViewModel.SaveNameCommand属性并Button.CommandParameter绑定到EmployeeNameTxBx.Text属性.
<StackPanel>
<TextBox x:Name="EmployeeNameTxBx"
Text="{Binding EmployeeName, Mode=OneWay}" />
<Button Content="OK"
Command="{Binding SaveNameCommand}"
CommandParameter="{Bidning Text, ElementName=EmployeeNameTxBx}" />
</StackPanel>
Run Code Online (Sandbox Code Playgroud)
在我的内部我EmployeeViewModel有OnSaveNameCommandExecute(object param)执行我的方法SaveNameCommand.
在此执行此代码...
var text = (string)param;
this.EmployeeName = text;
Run Code Online (Sandbox Code Playgroud)
这样只需单击OK按钮,将TextBox的文本更新回EmployeeName模型的属性.
编辑
查看下面的评论,我发现您正在尝试在UI上实现验证.现在这会改变一些事情.
IDataErrorInfo和相关验证仅在输入控件(如TextBoxes)是TwoWay绑定时才起作用.是的,这就是它的意图.所以现在你可能会问:"这是否意味着如果我们使用IDataErrorInfo,那么不允许将无效数据传递给模型的整个概念在MVVM中是徒劳的"?
并不是!
请参阅MVVM不强制执行仅返回有效数据的规则.它接受无效数据,这是如何IDataErrorInfo工作和引起错误通知.关键是ViewModel仅仅是对View的软拷贝,因此它可能很脏.应该确保的是,这种肮脏不会提交给您的外部接口,例如服务或数据库.
这种无效数据流应该ViewModel通过测试无效数据来限制.如果我们TwoWay启用了绑定,那么数据将会出现.因此,考虑到您正在实现,IDataErrorInfo那么您需要具有TwoWayMVVM中完全允许的绑定.
方法1:
如果我想在按钮点击时明确验证用户界面上的某些项目怎么办?
为此使用延迟验证技巧.在您的ViewModel中有一个名为isValidating的标志.默认情况下将其设置为false.
在您的IDataErrorInfo.this属性中,通过检查isValidating标志跳过验证...
string IDataErrorInfo.this[string columnName]
{
get
{
if (!isValidating) return string.Empty;
string result = string.Empty;
bool value = false;
if (columnName == "EmployeeName")
{
if (string.IsNullOrEmpty(AccountType))
{
result = "EmployeeName cannot be empty!";
value = true;
}
}
return result;
}
}
Run Code Online (Sandbox Code Playgroud)
然后在您的OK命令执行处理程序中,检查员工姓名,然后为同一属性提出属性更改通知事件...
private void OnSaveNameCommandExecute(object param)
{
isValidating = true;
this.NotifyPropertyChanged("EmployeeName");
isValidating = false;
}
Run Code Online (Sandbox Code Playgroud)
仅在单击"确定"时才会触发验证.请记住,EmployeeName必须包含无效数据才能使验证生效.
方法2:
如果我想在MVVM中显式更新没有TwoWay模式的绑定怎么办?
然后你将不得不使用Attached Behavior.该行为将附加到"确定"按钮,并将接受需要刷新其绑定的所有项目的列表.
<Button Content="OK">
<local:SpecialBindingBehavior.DependentControls>
<MultiBinding Converter="{StaticResource ListMaker}">
<Binding ElementName="EmployeeNameTxBx" />
<Binding ElementName="EmployeeSalaryTxBx" />
....
<MultiBinding>
</local:SpecialBindingBehavior.DependentControls>
</Button>
Run Code Online (Sandbox Code Playgroud)
这ListMaker是一个IMultiValueConverter简单的将值转换为列表...
Convert(object[] values, ...)
{
return values.ToList();
}
Run Code Online (Sandbox Code Playgroud)
在你SpecialBindingBehavior有一个DependentControls属性改变处理程序...
private static void OnDependentControlsChanged(
DependencyObject depObj,
DependencyPropertyChangedEventArgs e)
{
var button = sender as Button;
if (button != null && e.NewValue is IList)
{
button.Click
+= new RoutedEventHandler(
(object s, RoutedEventArgs args) =>
{
foreach(var element in (IList)e.NewValue)
{
var bndExp
= ((TextBox)element).GetBindingExpression(
((TextBox)element).Textproperty);
bndExp.UpdateSource();
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
但我仍然建议你使用我之前的纯MVVM**方法1.
| 归档时间: |
|
| 查看次数: |
6603 次 |
| 最近记录: |