В настоящее время я экспериментирую с 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
, но оно снова и снова запускается графическим интерфейсом, поэтому я почти уверен, что есть лучший способ.
Кто-нибудь знает, как я могу это исправить?
Поведение привязки TextBox по умолчанию заключается в обновлении привязки после того, как TextBox теряет фокус, поэтому ваше связанное свойство изменяется только ПОСЛЕ того, как пользователь вводит, а затем выполняет любое действие для потери фокуса на TextBox. Вы, очевидно, не можете использовать событие TextChanged, потому что оно будет срабатывать при каждом нажатии клавиши.
Лучший способ сохранить ваш MVVM и полагаться на то, что ограничивающее свойство изменится в первую очередь, — это полностью избавиться от вашего EventTrigger и вашего ICommand и просто воспользоваться преимуществами, когда вызывается ваш установщик DefaultPage.
В вашей 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}"/>
And setter
Вы можете получить значение, когда значение textBox изменилось.
class ViewModel
{
private string _defaultPage;
public string DefaultPage
{
get { return _DefaultPage; }
set { _DefaultPage = value; OpPropertyChanged(); DefaultPageChanged(value); }
}
private void DefaultPageChanged(string v)
{
// Service some...
}
}