ViewModel属性在改变TextBox文本时没有得到更新

本文关键字:更新 文本 属性 改变 TextBox ViewModel | 更新日期: 2023-09-27 18:08:30

我在UserControl中有一个TextBox,它被绑定到MainWindow的ViewModel属性。

现在,当我在文本框中输入的东西,它更新属性在视图模型,但如果我改变文本框后面的代码文本,视图模型属性不更新。

实际上,文本框从FileDialog中获取值,当我点击按钮时打开,所以文本框从后面的代码中获取文本。

用户控件XAML:

<StackPanel Orientation="Horizontal" Grid.Row="1" HorizontalAlignment="Left">
    <TextBox x:Name="TextBoxFileOrFolder" Text="{Binding FolderOrFileName}" Grid.Row="1" Width="200" Height="100" HorizontalAlignment="Left"></TextBox>
    <Button x:Name="ButtonRun" Content="Run" Click="ButtonRun_OnClick" Width="200" Height="100" Margin="10"></Button>
</StackPanel>

UserControl代码

private void ButtonRun_OnClick(object sender, RoutedEventArgs e)
{
    TextBoxFileOrFolder.Text = "FileName" + new Random().Next();
}

ViewModel:

public class MainViewModel: INotifyPropertyChanged
{
    public MainViewModel()
    { }
    private string folderOrFileName;
    public string FolderOrFileName
    {
        get { return folderOrFileName; }
        set
        {
            if (folderOrFileName!=value)
            {
                folderOrFileName = value;
                RaisePropertyChanged();
            }
        }
    }
    #region INotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;
    /// <summary>
    /// Raises the property changed.
    /// </summary>
    /// <param name="propertyName">Name of the property.</param>
    protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
    # endregion
}

ViewModel属性在改变TextBox文本时没有得到更新

但是如果我在后面的代码中改变Textbox的文本,viewmodel属性不会更新。

这是因为如果您在代码隐藏中设置文本框的Text属性,您将覆盖绑定。当你更新视图时,到视图模型的链接消失了,所以没有东西会更新它。而且,当视图模型更新值时,视图也不会被更新。

要解决这个问题,只需不要在代码后面设置有绑定的属性。

您应该将按钮命令绑定到视图模型并更新视图模型中的FolderOrFileName,而不是在代码隐藏中处理按钮事件并更新视图。

如果你绑定了Text属性,你应该在ViewModel中设置属性来改变TextBox的值:

public partial class MainWindow : Window
{
    private MainViewModel _vm;
    public MainWindow()
    {
        InitializeComponent();
        _vm = new MainViewModel();
        DataContext = _vm;
    }
    private void ButtonRun_OnClick(object sender, RoutedEventArgs e)
    {
        _vm.FolderOrFileName = "FileName" + new Random().Next();
    }
}

在你的情况下,你应该使用命令来修改数据。

1)你应该创建一个继承自ICommand的类:
public class DelegateCommand : ICommand
{
    private readonly Predicate<object> _canExecute;
    private readonly Action<object> _execute;
    public event EventHandler CanExecuteChanged;
    public DelegateCommand(Action<object> execute)
        : this(execute, null)
    {
    }
    public DelegateCommand(Action<object> execute,
                   Predicate<object> canExecute)
    {
        _execute = execute;
        _canExecute = canExecute;
    }
    public bool CanExecute(object parameter)
    {
        if (_canExecute == null)
        {
            return true;
        }
        return _canExecute(parameter);
    }
    public void Execute(object parameter)
    {
        _execute(parameter);
    }
    public void RaiseCanExecuteChanged()
    {
        if (CanExecuteChanged != null)
        {
            CanExecuteChanged(this, EventArgs.Empty);
        }
    }
}
2)接下来你应该在ViewModel中创建命令:
public class MainViewModel : INotifyPropertyChanged
{
    public MainViewModel()
    {
        ChangeFileName = new DelegateCommand(OnChangeFileName);
    }
    public ICommand ChangeFileName { get; private set; }
    private void OnChangeFileName(object param)
    {
        FolderOrFileName = "FileName" + new Random().Next();
    }
    private string folderOrFileName;
    ...

3)最后,你应该添加绑定到Button.Command属性在视图:

<Button x:Name="ButtonRun" Content="Run" Command="{Binding ChangeFileName}" Width="200" Height="100" Margin="10"></Button>

确保绑定设置为" two - way " - UI -> VM和VM -> UI

<TextBox x:Name="TextBoxFileOrFolder" Text="{Binding FolderOrFileName, Mode=TwoWay}" Grid.Row="1" Width="200" Height="100" HorizontalAlignment="Left"></TextBox>