【发布时间】:2011-01-12 13:43:26
【问题描述】:
我正在我的 XAML 中寻找正确的语法来设置我的 Viewmodel 中的属性(例如“BusyEditing”),然后它已经链接到按钮的“IsEnabled”绑定。 基本上,我希望在输入字段开始编辑时启用“保存”按钮。更酷的是,如果属性是在文本框值的更改时更新的,而不仅仅是 GotFocus。
提前致谢。
【问题讨论】:
我正在我的 XAML 中寻找正确的语法来设置我的 Viewmodel 中的属性(例如“BusyEditing”),然后它已经链接到按钮的“IsEnabled”绑定。 基本上,我希望在输入字段开始编辑时启用“保存”按钮。更酷的是,如果属性是在文本框值的更改时更新的,而不仅仅是 GotFocus。
提前致谢。
【问题讨论】:
您可以使用Commanding 轻松完成此操作。如果您将 ViewModel 上的命令绑定到您的按钮,并且 CanExecute 方法从您的其他输入中查找有效信息,那么它将保持禁用状态,直到满足该条件。
在MVVM Light 中看起来像这样
public RelayCommand LogonCommand { get; private set; }
LogonCommand = new RelayCommand(
Logon,
CanLogon
);
private Boolean CanLogon(){
return !String.IsNullOrWhiteSpance(SomeProperty);
}
在您的 XAML 中,只需确保将按钮命令绑定到 ViewModel 命令:
<Button Command="{Binding LogonCommand}" />
如果您的文本框绑定到 SomeProperty,则无需任何额外工作,也无需任何代码。
此外,如果您想使用 trigger on property change 而不是 LostFocus,则需要明确定义。
<TextBox>
<TextBox.Text>
<Binding Source="{StaticResource myDataSource}" Path="SomeProperty"
UpdateSourceTrigger="PropertyChanged"/>
</TextBox.Text>
</TextBox>
【讨论】:
执行此操作的最简单方法是在代码隐藏中,虽然这对 WPF 开发人员来说有点小题大做,但它是视图逻辑,不会破坏单元测试的可能性。
<TextBox GotFocus="GotFocus"/>
<Button Name="SaveButton" Command="{Binding SaveCommand}" IsEnabled="False">
<TextBlock Text="Save"/>
</Button>
然后
private void GotFocus( object sender, RoutedEventArgs e )
{
SaveButton.IsEnabled = true;
}
或者,您可以将命令附加到 GotFocus 事件 (http://stackoverflow.com/questions/1048517/wpf-calling-commands-via-events) 在视图模型上设置一个布尔值,该值也在“SaveCommand”中查询" CanExecute 方法。
【讨论】:
听起来您想将属性命名为 IsDirty,并且仅在模型变脏时才使“保存”按钮可用。您可以在视图模型上有一个 CanSave 属性,该属性在加载模型时检查新模型值与原始值,例如:
public bool CanSave
{
get
{
return this.IsDirty;
}
}
public bool IsDirty
{
get
{
if (this.ModelPropertyValue != this.ModelOriginalPropertyValue)
{
return true;
}
return false;
}
}
private string modelPropertyValue;
public string ModelPropertyValue
{
get
{
return this.modelPropertyValue;
}
set
{
if (this.modelPropertyValue == value)
{
return;
}
this.modelPropertyValue = value;
OnPropertyChanged(() => this.ModelPropertyValue);
OnPropertyChanged(() => this.CanSave);
}
}
默认情况下,文本框仅在失去焦点时更新其绑定属性,因此您需要在文本框上设置 UpdateSourceTrigger 属性:
<TextBox Text="{Binding ModelPropertyValue, UpdateSourceTrigger=PropertyChanged}" />
<Button IsEnabled="{Binding CanSave}">Save</Button>
【讨论】:
您需要使用EventTrigger。事实上,他们两个。一个用于GotFocus,另一个用于LostFocus 事件。
这是一个例子:
Using EventTrigger in XAML for MVVM – No Code Behind Code
寻找SetProperty 触发动作。这对你很有用。
【讨论】:
如果您只有一个文本框,那么懒惰、快速且不那么优雅的解决方案:
<TextBox Name="TB" Width="200"/>
<Button Content="Save">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=TB, Path=Text}" Value="">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
一旦文本框中有文本,按钮就会被启用。
【讨论】: