You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何通过ViewModel方法更新属性后刷新WPF视图元素显示?

解决WPF视图在命令执行后不更新的问题

我来帮你排查并解决这个问题,你的代码里有两个关键问题导致视图无法正常更新:


1. ViewModel的Status属性未触发属性变更通知

你的MsgViewModel没有实现INotifyPropertyChanged接口,而且Status属性更新时没有向视图发送变更通知。虽然你的MsgModel实现了该接口,但视图绑定的是ViewModel的Status属性,而非Model的。当你在Egzecute方法中修改Status时,ViewModel没有告诉视图这个属性发生了变化,所以视图不会做出响应。

修复方法:

MsgViewModel实现INotifyPropertyChanged接口,并在Status属性的setter中触发PropertyChanged事件:

public class MsgViewModel : INotifyPropertyChanged
{
    private Models.MsgModel message = new Models.MsgModel();

    public MsgViewModel()
    {
        Status = Models.SendingStatus.Stopped;
    }

    public Models.SendingStatus Status
    {
        get { return message.Status; }
        set 
        { 
            if (message.Status != value)
            {
                message.Status = value;
                OnPropertyChanged(nameof(Status)); // 触发属性变更通知
            }
        }
    }

    // 实现INotifyPropertyChanged接口
    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    // 你的Command和Egzecute方法保持不变
    private ICommand start;
    public ICommand Start
    {
        get
        {
            if (start == null)
                start = new RelayCommand(o => { Egzecute(); });
            return start;
        }
    }

    public void Egzecute()
    {
        Status = Models.SendingStatus.Sending;
        var openDialog = new Powiadomienie();
        openDialog.ShowPowiadomienie(Status.ToString(), "Powiadomienie");
    }
}

2. 转换器(Converter)的逻辑错误

你的BooleanStartBooleanStop转换器里犯了一个致命错误:每次转换时都新建了一个MsgViewModel实例,这个新实例的Status永远是默认的Stopped,所以转换器永远判断的是新实例的状态,不是当前绑定的ViewModel的真实状态。

修复方法:

转换器应该直接使用当前绑定的数据源(也就是页面的MsgViewModel),而不是新建实例。我们可以修改绑定逻辑,让转换器直接接收Status属性值:

第一步:修改View的绑定,直接绑定ViewModel的Status属性

<!--START按钮,绑定Status属性到转换器-->
<Button Grid.Row="0" Grid.Column="4" Background="#80B584"
        Visibility="{Binding Status, Converter={StaticResource boolStart}}"
        Margin="0,145,443.667,-0.333" Command="{Binding Path=Start}">
    <TextBlock Text="START" TextWrapping="Wrap" TextAlignment="Center"/>
</Button>

<!--STOP按钮,绑定Status属性到转换器-->
<Button Grid.Row="0" Background="#FF8A8A"
        Visibility="{Binding Status, Converter={StaticResource boolStop}}"
        Margin="0,145,443.667,-0.333">
    <TextBlock Text="STOP" TextWrapping="Wrap" TextAlignment="Center"/>
</Button>

第二步:修正转换器逻辑,直接处理SendingStatus枚举值

public class BooleanStart : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is Models.SendingStatus status)
        {
            // 当状态是Sending或Waiting时,隐藏START按钮
            return status == Models.SendingStatus.Sending || status == Models.SendingStatus.Waiting 
                ? Visibility.Collapsed 
                : Visibility.Visible;
        }
        return Visibility.Visible; // 默认显示
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

public class BooleanStop : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is Models.SendingStatus status)
        {
            // 当状态是Sending或Waiting时,显示STOP按钮
            return status == Models.SendingStatus.Sending || status == Models.SendingStatus.Waiting 
                ? Visibility.Visible 
                : Visibility.Collapsed;
        }
        return Visibility.Collapsed; // 默认隐藏
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

额外优化建议

  • 检查你的RelayCommand是否正确实现了ICommand接口,确保CanExecuteChanged事件能正常触发(不过这个问题里主要是属性通知的问题)。
  • 可以考虑把两个转换器合并成一个,通过parameter参数区分是START还是STOP按钮,减少冗余代码。

做完以上修改后,当你点击START按钮执行命令、修改Status属性时,ViewModel会通知视图属性变更,转换器会根据当前状态正确切换按钮的可见性。

内容的提问来源于stack exchange,提问作者user8532173

火山引擎 最新活动