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

C# 传入WCF消息后WPF UI未更新,c#,wpf,user-interface,mvvm,C#,Wpf,User Interface,Mvvm,我有一个MVVM应用程序,我的ViewModelPingServiceWModel处理传入的WCFPing()消息。处理此类消息发生在调度程序的线程上。默认值为的线程池。 从语义上讲,传入的WCF消息更改绑定属性扫描,并引发所述属性的PropertyChanged事件 但我的用户界面在收到一些用户界面事件(例如聚焦/单击窗口等)之前不会更新。 如何在事件触发后立即进行更新? 我已经试着提出财产变更事件 在应用程序的调度程序上 使用SynchronizationContext 没有任何运气 我

我有一个MVVM应用程序,我的ViewModel
PingServiceWModel
处理传入的WCF
Ping()
消息。处理此类消息发生在
调度程序的线程上。默认值为
的线程池。
从语义上讲,传入的WCF消息更改绑定属性
扫描
,并引发所述属性的PropertyChanged事件

但我的用户界面在收到一些用户界面事件(例如聚焦/单击窗口等)之前不会更新。
如何在事件触发后立即进行更新?

我已经试着提出财产变更事件

  • 在应用程序的调度程序上
  • 使用SynchronizationContext
没有任何运气

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

下面是一些代码():
我的视图主窗口的一部分。xaml:
值得注意的是,bound
命令
实际上在生成传入的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}" />
我的ViewModel的一部分

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; }
    //...
}

如果您的CanPing属性和ping命令的CanExecute方法都返回TRUE,那么它应该可以工作

有时,委托/RelayCommand实现允许调用RaiseCanceTechChanged()-如果上述语句对这两个对象都为真且不起作用,请尝试此操作

顺便说一句,这是在raisecancecutechanged()中调用的


我认为您需要从按钮中删除IsEnabled=“{Binding CanPing}”

绑定到命令就足够了,因为ICommand对象包含CanExecuteCanExecuteChanged事件处理程序

我将在您的命令类中创建一个CanExecute boolean,并在此类上实现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方法上,在命令内更新此属性:

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");
}

您可以使用所述属性的
raisecancecutechanged()
方法进行更新。
例如:


试试这个,我希望它能解决你的问题。

你能发布ViewModel类吗?我更新了我的问题。注意:绑定到按钮的命令在生成传入的WCF消息时不起作用。问题的核心是我没有意识到绑定
命令
会处理
IsEnabled
属性。最后,我不需要
CanExecute1
属性,因为在我的ViewModel中,我可以调用
PingCommand.OnCanExecuteChanged()
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));
    }
}
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");
}
this.PingCommand.RaiseCanExecuteChanged();