c# - 传入 WCF 消息后 WPF UI 未更新

标签 c# wpf user-interface mvvm

我有一个 MVVM 应用程序,其中我的 ViewModel PingerViewModel处理传入的 WCF Ping()消息。处理此类消息发生在 Scheduler.Default 的线程上。的线程池。
从语义上讲,传入的 WCF 消息会更改绑定(bind)属性 CanPing并为所述属性引发 PropertyChanged 事件。

但是我的 UI 没有更新 直到它收到一些 UI 事件,例如聚焦/单击窗口等
事件触发后如何使其更新?

我试过引发 PropertyChanged 事件......

  • 在应用程序的调度程序上,
  • 使用 SynchronizationContext

  • 没有任何运气。

    我还验证了绑定(bind)属性确实设置为正确的值,并且确实有一个监听器正在使用我的 PropertyChanged 事件。

    这是一些代码(full code on github):
    我的 View MainWindow.xaml 的一部分:
    可能值得注意的是,绑定(bind) Command实际上在生成传入的 WCF 消息中没有任何作用。
    <Button Content="Ping" Height="23" HorizontalAlignment="Left" Margin="10,10,0,0" Name="PingBtn" VerticalAlignment="Top" Width="75" AutomationProperties.AutomationId="Ping" 
                IsEnabled="{Binding CanPing}" 
                Command="{Binding PingCommand}" />
    

    我的部分观点 MainWindow.xaml.cs
    public MainWindow()
    {
        DataContext = new PingerViewModel();
        InitializeComponent();
    }
    

    我的 View 模型的一部分
    public class PingerViewModel : INotifyPropertyChanged
        public PingerViewModel()
        {
            Pinger = new Pinger(true);
            PingCommand = new PingerPingCommand(this);
            //...
        }
    
        public bool CanPing
        {
            get
            {
                if (Pinger == null) return false;
                return Pinger.CanPing;
            }
        }
    
        public void Ping()
        {
            _pingClient.Channel.Ping();
            Pinger.CanPing = false;
            OnPropertyChanged("CanPing");
        }
    
        protected virtual void OnPong(PongEventArgs e)
        {
            Pinger.CanPing = true;
            OnPropertyChanged("CanPing");
        }
    
        public Pinger Pinger { get; private set; }
    
        public ICommand PingCommand { get; private set; }
        //...
    }
    

    最佳答案

    我认为您需要删除 IsEnabled="{绑定(bind) CanPing}"从您的按钮。

    绑定(bind)到命令就足够了,因为 ICommand 对象包含 可以执行 可以执行已更改 事件处理程序。

    我会在你的 Command 类中创建一个 CanExecute bool 值,并在这个类上实现 INotifyPropertyChanged。像这样的东西:

    public class PingCommand : ICommand, INotifyPropertyChanged
    {
        private bool _canExecute;
    
        public bool CanExecute1
        {
            get { return _canExecute; }
            set
            {
                if (value.Equals(_canExecute)) return;
                _canExecute = value;
                CanExecuteChanged.Invoke(null, null);
                OnPropertyChanged("CanExecute1");
            }
        }
    
        public void Execute(object parameter)
        {
            //whatever
        }
    
        public bool CanExecute(object parameter)
        {
            return _canExecute;
        }
    
        public event EventHandler CanExecuteChanged;
        public event PropertyChangedEventHandler PropertyChanged;
    
        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged(string propertyName)
        {
            var handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    

    然后,在 ViewModel 中的 Ping/Pong 方法上,更新 Command 中的此属性:
    public void Ping()
    {
        _pingClient.Channel.Ping();
        Pinger.CanPing = false;
        PingCommand.CanExecute1 = false;
        OnPropertyChanged("CanPing");
    }
    
    protected virtual void OnPong(PongEventArgs e)
    {
        Pinger.CanPing = true;
        PingCommand.CanExecute1 = true;
        OnPropertyChanged("CanPing");
    }
    

    关于c# - 传入 WCF 消息后 WPF UI 未更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18125610/

    相关文章:

    c# - 反射中的隐式类型转换

    c# - 如何将 List<object> 动态绑定(bind)到 WPF 中的 DataGrid?

    javascript - HTML/PHP 内使用 ZinoUI 的简单用户界面

    c# - 如何在 ASP.NET GridView 中的 BoundField 上方添加一行

    c# - 将python模块转换成DLL文件

    c# - 是否可以在 Global.asax 中添加对服务层的静态引用?

    wpf - 绑定(bind)到表达式

    wpf - 如何阻止面板的子项超出设置的面板最大宽度的范围?

    java - JavaFX 的标题面板(矩形命名区域控件)?

    python - 在 OS-X 中使用鼠标启动 Python 脚本的简便方法