如何在 MVVM WPF 中刷新 UI

Posted

技术标签:

【中文标题】如何在 MVVM WPF 中刷新 UI【英文标题】:How can I refresh the UI in MVVM WPF 【发布时间】:2012-09-23 09:04:13 【问题描述】:

我的项目基于 MVVM 模式。

我已经建立了一个树形视图来显示我的文件系统。 每个文件夹都有一个用于选择当前文件夹的复选框。 选择过程需要一些时间,所以在操作运行时,有一个按钮被禁用,在操作结束时我正在启用该按钮。

我的问题是,当按钮被“禁用”时,我会立即看到它。但是,当按钮返回启用模式时,我必须执行一些操作(如鼠标单击)才能看到按钮启用。

如何确保在启用按钮后立即更新 UI?

这些是我的按钮:

<Button Content="&lt;- Back" Margin="5,0,5,0" Width="80" Height="25"
        IsEnabled="Binding CanMoveToPreviousPage, UpdateSourceTrigger=PropertyChanged" 
        Command="Binding Path=NavigateBackCommand, IsAsync=True" />

<Button Content="Binding ButtonNextCaption" Margin="5,0,5,0" Width="80" Height="25"
        IsEnabled="Binding CanMoveToNextPage, UpdateSourceTrigger=PropertyChanged" 
        Command="Binding Path=NavigateNextCommand, IsAsync=True" />

在我的 ViewModel 中,我添加了以下代码:

public bool CanMoveToNextPage

    get
    
        return this.CurrentPage != null && this.CurrentPage.CanMoveNext;
    
    set
    
        if (CurrentPage != null)
        
            this.CurrentPage.CanMoveNext = value;
            OnPropertyChanged("CanMoveToNextPage");
        
    


public bool CanMoveToPreviousPage

    get  return 0 < this.CurrentPageIndex && CurrentPage.CanMoveBack; 
    set
    
        if (CurrentPage != null)
        
            this.CurrentPage.CanMoveBack = value;
            OnPropertyChanged("CanMoveToPreviousPage");
        
    

UI 更新发生在我执行鼠标单击或任何按键操作之后。

这是禁用和启用按钮的操作代码:

void bg_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)

    DecrementDoneCounter();
    if (ThreadSafeCouner == 0)//means all bg workers are done
    
        UIlimitation(true);
    


private int ThreadSafeCouner; // check how many bgworkers run
public void IncrementDoneCounter()  Interlocked.Increment(ref ThreadSafeCouner); 
public void DecrementDoneCounter()  Interlocked.Decrement(ref ThreadSafeCouner); 


void bg_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)

    IncrementDoneCounter();
    UIlimitation(false);
    ((bgArguments)e.Argument).SelectedDirectory.CanSelected = false;
    MarkItems(((bgArguments)e.Argument).SelectedDirectory, ((bgArguments)e.Argument).IsSelect);
    ((bgArguments)e.Argument).FreeWorkerAllocation();
    ((bgArguments)e.Argument).SelectedDirectory.CanSelected = true;


//this is the enabling action which execute the propeties setters at the upper part of this post
private static void UIlimitation(bool limit)

    MainWindowViewModel.Instance.CanMoveToNextPage = limit;
    MainWindowViewModel.Instance.CanMoveToPreviousPage = limit;

我能做什么?

【问题讨论】:

试试 this.UpdateLayout() 或 ButtonsParent.UpdateLayout() 当您的操作完成后,您是否为负责启用/禁用按钮的相关属性引发 OnPropertyChanged 事件? 完成后,我正在更改启用的属性,但 Set... 和 Set 包含 OnPropertyChanged 事件。当我尝试调试一切正常时,无需单击即可启用按钮。我可以弄清楚是什么问题 我在引发事件时添加了代码。感谢您的帮助 【参考方案1】:

您可以在控件上调整Binding mode TwoWay 并定义triggers with PropertyChanged

Binding ElementName=.., Mode=TwoWay, UpdateSourceTrigger=PropertyChanged

【讨论】:

我做到了,但问题仍然存在。 MVVM 模型应该实现 INotifyPropertyChanged,以便向控件发送通知【参考方案2】:

好的,我找到了解决方案。 我尝试了一切都没有成功,最终我找到了这个线程: Refresh WPF Command

我用过CommandManager.InvalidateRequerySuggested()

及其作品。

感谢您的帮助

【讨论】:

【参考方案3】:

这是一个代码示例,说明如何使用 INotifyPropertyChanged 发送消息以更新 UI 的方法设置 ViewModel:

public class MyViewModel : INotifyPropertyChanged

    /******************************************************/
    /* Property that you have created two-way binding for */
    /******************************************************/
    private double _myProperty
    public double MyProperty
    
        get  return _myProperty; 
        set
        
            _myProperty = value;

            OnNotifyPropertyChanged("MyProperty");
        
    

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnNotifyPropertyChanged(string propertyName)
    
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    

    #endregion INotifyPropertyChanged Members

【讨论】:

确保 OnNotifyPropertyChanged("MyProperty"); 的值是对的。

以上是关于如何在 MVVM WPF 中刷新 UI的主要内容,如果未能解决你的问题,请参考以下文章

WPF MVVM里,当用户在新窗口执行完后如何返回原窗口,并刷新

WPF MVVM框架引入

WPF MVVM 文本框文本绑定与 changedText 事件

如何在 Qt/C++/QML 中实现类似 WPF 的 MVVM?

WPF 如何将主题应用于使用 MVVM 动态创建的对象

无法使用 PRISM 5、MVVM 和 EF 6 在 WPF 中刷新 DataGrid