如何从ViewModel访问、修改按钮内容并根据状态执行对应命令
解决方案
MVVM架构下不建议ViewModel直接访问视图层的按钮控件,通过属性绑定即可实现按钮文本的动态切换,具体实现如下:
步骤1:改造基础ViewModel类
首先让ViewModel实现INotifyPropertyChanged接口,新增连接状态、按钮文本两个可通知绑定属性,同时修复原有代码中局部变量覆盖类成员client的问题:
using System.ComponentModel; using System.Net.Sockets; using System.Windows; namespace firstApp { public class ViewModel : INotifyPropertyChanged { public TcpClient client = null; public ICommand MyCommand { get; set; } // 新增连接状态属性 private bool _isConnected; public bool IsConnected { get => _isConnected; set { _isConnected = value; OnPropertyChanged(nameof(IsConnected)); // 状态变更时同步修改按钮文本 ConnectButtonText = _isConnected ? "Disconnect" : "Connect"; } } // 新增按钮文本绑定属性 private string _connectButtonText = "Connect"; public string ConnectButtonText { get => _connectButtonText; set { _connectButtonText = value; OnPropertyChanged(nameof(ConnectButtonText)); } } public ViewModel() { MyCommand = new Command(ExecuteMethod, canExecuteMethod); } private bool canExecuteMethod(object parameter) { return true; } public void ExecuteMethod(object parameter) { try { Int32 port = 8000; if (!IsConnected) { // 移除局部变量声明,直接给类成员client赋值 client = new TcpClient("127.0.0.1", port); IsConnected = true; } else { client.Close(); IsConnected = false; } } catch (ArgumentNullException ex) { MessageBox.Show(ex.Message); } catch (SocketException ex) { MessageBox.Show(ex.Message); } } // 实现属性变更通知 public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } }
步骤2:修正SendViewModel逻辑
原有SendViewModel构造函数错误绑定了MyCommand,需要修正为绑定MySendCommand:
namespace firstApp { public class SendViewModel: ViewModel { public ICommand MySendCommand { get; set; } public SendViewModel() { // 修正命令绑定 MySendCommand = new Command(ExecuteSendMethod, canExecuteMethod); } private bool canExecuteMethod(object parameter) { return IsConnected; } public void ExecuteSendMethod(object parameter) { if (IsConnected) { Byte[] data = System.Text.Encoding.ASCII.GetBytes("hello"); NetworkStream stream = client.GetStream(); stream.Write(data, 0, data.Length); } else { MessageBox.Show("There is no connection"); } } } }
步骤3:XAML绑定配置
直接将按钮的Content属性绑定到ViewModel的ConnectButtonText即可,无需手动操作控件:
<Button Content="{Binding ConnectButtonText}" Command="{Binding MyCommand}"/> <!-- 发送按钮绑定示例 --> <Button Content="发送" Command="{Binding MySendCommand}"/>
点击按钮后Command执行逻辑会自动修改ConnectButtonText的值,视图会自动同步更新按钮显示内容。
内容的提问来源于stack exchange,提问作者grif_noob
相关产品推荐
相关产品推荐

