我在UserControl中有一个TextBox,它绑定到MainWindow的ViewModel中的属性。
现在,当我在文本框中键入内容时,它会更新viewmodel中的属性,但如果我在后面的代码中更改Textbox的文本,则viewmodel属性不会更新。
实际上文本框是从FileDialog获取的值,当我点击按钮时会打开它,因此Textbox会从后面的代码中获取文本。
UserControl 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();
}
视图模型:
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
}
答案 0 :(得分:4)
但如果我在后面的代码中更改Textbox的文本,则viewmodel属性不会更新。
那是因为如果在代码隐藏中设置文本框的Text
属性,则会覆盖绑定。因此,在更新视图时,视图模型的链接已消失,因此没有任何内容可以更新它。而且,当视图模型更新值时,视图也不会更新。
要解决此问题,请不要在代码隐藏中设置具有绑定的属性。
您应该让按钮命令绑定到视图模型并更新视图模型中的FolderOrFileName
,而不是处理代码隐藏中的按钮事件并更新视图。
答案 1 :(得分:3)
如果绑定到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)最后你应该在View:
中添加Button.Command
属性的绑定
<Button x:Name="ButtonRun" Content="Run" Command="{Binding ChangeFileName}" Width="200" Height="100" Margin="10"></Button>
答案 2 :(得分:0)
确保您的绑定设置为&#34; TwoWay&#34; - UI - &gt; VM和VM - &gt; UI
<TextBox x:Name="TextBoxFileOrFolder" Text="{Binding FolderOrFileName, Mode=TwoWay}" Grid.Row="1" Width="200" Height="100" HorizontalAlignment="Left"></TextBox>