WPF 如何使用 MVVM 模式将值正确绑定到 TextBox
WPF how to bind value to TextBox correclty with MVVM pattern
我目前正在试验 WPF。我使用 Windows Template Studio 为 Visual Studio.
创建了一个演示项目
现在我想添加一个应该由 MVVM 模式自动保存的文本框。我将以下 XAML 添加到我的设置页面。
<TextBlock
Style="{StaticResource BodyTextStyle}"
Text="Default Page" />
<TextBox Text="{Binding DefaultPage}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="TextChanged">
<i:InvokeCommandAction Command="{Binding SetDefaultPageCommand}" CommandParameter="{Binding DefaultPage}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
在 SettingsViewModel
中,我添加了以下几行:
private readonly IDefaultPageService _defaultPageService;
private string _defaultPage;
public ICommand SetDefaultPageCommand => _setDefaultPageCommand ?? (_setDefaultPageCommand = new RelayCommand<string>(OnSetDefaultPage));
public string DefaultPage
{
get { return _defaultPage; }
set { Set(ref _defaultPage , value); }
}
private void OnSetDefaultPage(string defaultPage)
{
_defaultPageService.SetDefaultPage(defaultPage);
}
要保存的服务实现为:
public class DefaultPageService : IDefaultPageService
{
public DefaultPageService()
{
}
public void InitializeDefaultPage()
{
var theme = GetDefaultPage();
SetDefaultPage(theme);
}
public void SetDefaultPage(string defaultPage)
{
App.Current.Properties["DefaultPage"] = defaultPage.ToString();
}
public string GetDefaultPage()
{
if (App.Current.Properties.Contains("DefaultPage"))
{
var defaultPage = App.Current.Properties["DefaultPage"].ToString();
return defaultPage;
}
return "https://google.com";
}
}
保存我的新字符串有效,但不幸的是,我的命令在实际绑定 属性 更改其值之前被调用。我已经尝试了一堆不同的 TextBox 事件,例如 KeyUp
和 KeyDown
。我发现唯一有效的事件是 LayoutUpdated
但这个事件被 GUI 一遍又一遍地触发,所以我很确定有更好的方法。
有人知道我该如何解决这个问题吗?
TextBox 绑定的默认行为是在 TextBox 失去焦点后更新绑定,这就是为什么您的绑定 属性 仅在用户键入然后执行任何操作以失去焦点后才会更改文本框。您显然不能使用 TextChanged 事件,因为它会在每次击键时触发。
保留 MVVM 并依赖边界 属性 来更改 first 的最佳方法是完全摆脱 EventTrigger 和 ICommand,并且简单利用您的 DefaultPage setter 被调用的时间。
在您的 SettingsViewModel 中:
private readonly IDefaultPageService _defaultPageService;
private string _defaultPage;
public string DefaultPage
{
get { return _defaultPage; }
set { Set(ref _defaultPage , value); OnSetDefaultPage(_defaultPage); }
}
private void OnSetDefaultPage(string defaultPage)
{
_defaultPageService.SetDefaultPage(defaultPage);
}
添加绑定选项
UpdateSourceTrigger=PropertyChanged
<TextBox Text="{Binding DefaultPage, UpdateSourceTrigger=PropertyChanged}"/>
并且 setter
当文本框值改变时,您可以获取值。
class ViewModel
{
private string _defaultPage;
public string DefaultPage
{
get { return _DefaultPage; }
set { _DefaultPage = value; OpPropertyChanged(); DefaultPageChanged(value); }
}
private void DefaultPageChanged(string v)
{
// Service some...
}
}
我目前正在试验 WPF。我使用 Windows Template Studio 为 Visual Studio.
创建了一个演示项目现在我想添加一个应该由 MVVM 模式自动保存的文本框。我将以下 XAML 添加到我的设置页面。
<TextBlock
Style="{StaticResource BodyTextStyle}"
Text="Default Page" />
<TextBox Text="{Binding DefaultPage}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="TextChanged">
<i:InvokeCommandAction Command="{Binding SetDefaultPageCommand}" CommandParameter="{Binding DefaultPage}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
在 SettingsViewModel
中,我添加了以下几行:
private readonly IDefaultPageService _defaultPageService;
private string _defaultPage;
public ICommand SetDefaultPageCommand => _setDefaultPageCommand ?? (_setDefaultPageCommand = new RelayCommand<string>(OnSetDefaultPage));
public string DefaultPage
{
get { return _defaultPage; }
set { Set(ref _defaultPage , value); }
}
private void OnSetDefaultPage(string defaultPage)
{
_defaultPageService.SetDefaultPage(defaultPage);
}
要保存的服务实现为:
public class DefaultPageService : IDefaultPageService
{
public DefaultPageService()
{
}
public void InitializeDefaultPage()
{
var theme = GetDefaultPage();
SetDefaultPage(theme);
}
public void SetDefaultPage(string defaultPage)
{
App.Current.Properties["DefaultPage"] = defaultPage.ToString();
}
public string GetDefaultPage()
{
if (App.Current.Properties.Contains("DefaultPage"))
{
var defaultPage = App.Current.Properties["DefaultPage"].ToString();
return defaultPage;
}
return "https://google.com";
}
}
保存我的新字符串有效,但不幸的是,我的命令在实际绑定 属性 更改其值之前被调用。我已经尝试了一堆不同的 TextBox 事件,例如 KeyUp
和 KeyDown
。我发现唯一有效的事件是 LayoutUpdated
但这个事件被 GUI 一遍又一遍地触发,所以我很确定有更好的方法。
有人知道我该如何解决这个问题吗?
TextBox 绑定的默认行为是在 TextBox 失去焦点后更新绑定,这就是为什么您的绑定 属性 仅在用户键入然后执行任何操作以失去焦点后才会更改文本框。您显然不能使用 TextChanged 事件,因为它会在每次击键时触发。
保留 MVVM 并依赖边界 属性 来更改 first 的最佳方法是完全摆脱 EventTrigger 和 ICommand,并且简单利用您的 DefaultPage setter 被调用的时间。
在您的 SettingsViewModel 中:
private readonly IDefaultPageService _defaultPageService;
private string _defaultPage;
public string DefaultPage
{
get { return _defaultPage; }
set { Set(ref _defaultPage , value); OnSetDefaultPage(_defaultPage); }
}
private void OnSetDefaultPage(string defaultPage)
{
_defaultPageService.SetDefaultPage(defaultPage);
}
UpdateSourceTrigger=PropertyChanged
<TextBox Text="{Binding DefaultPage, UpdateSourceTrigger=PropertyChanged}"/>
并且 setter
当文本框值改变时,您可以获取值。
class ViewModel
{
private string _defaultPage;
public string DefaultPage
{
get { return _DefaultPage; }
set { _DefaultPage = value; OpPropertyChanged(); DefaultPageChanged(value); }
}
private void DefaultPageChanged(string v)
{
// Service some...
}
}