Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF MVVM Light-取消viewmodel中的属性更改-RaisePropertyChanged,即使值与以前相同_C#_Wpf_Mvvm Light - Fatal编程技术网

C# WPF MVVM Light-取消viewmodel中的属性更改-RaisePropertyChanged,即使值与以前相同

C# WPF MVVM Light-取消viewmodel中的属性更改-RaisePropertyChanged,即使值与以前相同,c#,wpf,mvvm-light,C#,Wpf,Mvvm Light,我有一个绑定到组合框的属性(在viewmodel中)。 当viewmodel属性更改时,它将使用Messenger通知另一个viewmodel 然后,另一个viewmodel决定这是否正常,如果不正常,我想取消并将旧值发送回视图 我想我可以先将值设置为新值,然后再将其设置回原来的值。但是有更优雅的解决方案吗 失败代码 我设法用这个变通方法解决了它,但我不喜欢它:( 乍一看,这似乎是不正确的,但调用堆栈使它这样做 在SelectedItem上使用单向绑定并使用命令交互触发器 棘手的解决办法 您需要

我有一个绑定到组合框的属性(在viewmodel中)。 当viewmodel属性更改时,它将使用Messenger通知另一个viewmodel

然后,另一个viewmodel决定这是否正常,如果不正常,我想取消并将旧值发送回视图

我想我可以先将值设置为新值,然后再将其设置回原来的值。但是有更优雅的解决方案吗

失败代码

我设法用这个变通方法解决了它,但我不喜欢它:( 乍一看,这似乎是不正确的,但调用堆栈使它这样做

在SelectedItem上使用单向绑定并使用命令交互触发器

棘手的解决办法


您需要使用
Dispatcher.BeginInvoke

来执行用户操作的反转

基本上,当用户选择组合框上的项目时,WPF将忽略拒绝该值的任何尝试。但是,如果您等待与数据绑定相关的所有代码完成,则基本上可以启动新的绑定活动。这就是
Dispatcher.BeginInvoke
所做的。它允许您将所选项目重置为be推迟到绑定引擎完成其工作

例如:

public class MainViewModel : ViewModelBase
{
    private string _selectedItem;

    public List<string> Items { get; private set; }

    public string SelectedItem
    {
        get { return _selectedItem; }
        set
        {
            if (value == _selectedItem) return;
            var previousItem = _selectedItem;
            _selectedItem = value;
            var isInvalid = value == "Bus"; // replace w/ your messenger code
            if (isInvalid)
            {
                Application.Current.Dispatcher.BeginInvoke(
                    new Action(() => ResetSelectedItem(previousItem)),
                    DispatcherPriority.ContextIdle,
                    null);
                return;
            }
            RaisePropertyChanged();
        }
    }

    public MainViewModel()
    {
        Items = new[] { "Car", "Bus", "Train", "Airplane" }.ToList();
        _selectedItem = "Airplane";
    }

    private void ResetSelectedItem(string previousItem)
    {
        _selectedItem = previousItem;
        RaisePropertyChanged(() => SelectedItem);
    }
}
public类MainViewModel:ViewModelBase
{
私有字符串_selectedItem;
公共列表项{get;private set;}
公共字符串SelectedItem
{
获取{return\u selectedItem;}
设置
{
如果(值==_selectedItem)返回;
var previousItem=\u selectedItem;
_选择editem=值;
var isInvalid=value==“总线”//替换您的messenger代码
如果(isInvalid)
{
Application.Current.Dispatcher.BeginInvoke(
新操作(()=>ResetSelectedItem(上一项)),
DispatcherPriority.ContextIdle,
无效);
返回;
}
RaisePropertyChanged();
}
}
公共主视图模型()
{
Items=新[]{“汽车”、“公共汽车”、“火车”、“飞机”}.ToList();
_选择editem=“飞机”;
}
private void ResetSelectedItem(字符串previousItem)
{
_选择editem=上一项;
RaisePropertyChanged(()=>SelectedItem);
}
}

啊,ContextIdle可能是这里的诀窍?我很快就会尝试。但我认为它会起作用:)在图像渲染/保存时使用了相同的诀窍。是否最好避免使用调度程序,而是使用
SynchronizationContext.Current.Post
public DeckType SelectedDeckType
{
    get { return _selectedDeckType; }
    set
    {
        _selectedDeckType = value;
        RaisePropertyChanged();
    }
}

public ICommand SelectedDeckTypeChangedCommand { get; private set; }

private void ExecuteSelectedItemChangedCommand(DeckType aDeckType)
{
    try
    {
        if (_previousSelectedDeckType == aDeckType)
        {
            return;
        }
        _previousSelectedDeckType = aDeckType;

        DeckTypeMessage deckTypeMessage = new DeckTypeMessage(this, aDeckType);
        Messenger.Default.Send(deckTypeMessage);
        if (deckTypeMessage.IsCancel)
        {
            SelectedDeckType = _selectedDeckType;
            _previousSelectedDeckType = _selectedDeckType;
            return;
        }

        SelectedDeckType = aDeckType;
    }
    catch (Exception ex)
    {
        NotifyMediator.NotifiyException(new NotifyMediator.NotifyInformation(NotifyMediator.NotificationLevel.Error, ex));
    }
}
public class MainViewModel : ViewModelBase
{
    private string _selectedItem;

    public List<string> Items { get; private set; }

    public string SelectedItem
    {
        get { return _selectedItem; }
        set
        {
            if (value == _selectedItem) return;
            var previousItem = _selectedItem;
            _selectedItem = value;
            var isInvalid = value == "Bus"; // replace w/ your messenger code
            if (isInvalid)
            {
                Application.Current.Dispatcher.BeginInvoke(
                    new Action(() => ResetSelectedItem(previousItem)),
                    DispatcherPriority.ContextIdle,
                    null);
                return;
            }
            RaisePropertyChanged();
        }
    }

    public MainViewModel()
    {
        Items = new[] { "Car", "Bus", "Train", "Airplane" }.ToList();
        _selectedItem = "Airplane";
    }

    private void ResetSelectedItem(string previousItem)
    {
        _selectedItem = previousItem;
        RaisePropertyChanged(() => SelectedItem);
    }
}