【问题标题】:WPF Control binding does not always update UIWPF 控件绑定并不总是更新 UI
【发布时间】:2019-04-16 22:07:55
【问题描述】:

我有一个按钮,其IsEnabled 属性在我的视图模型中绑定到一个值,该值指示当前视图中的数据是否已被修改。到目前为止,此绑定一直运行良好,直到我尝试将拖放功能添加到视图中的 ItemsControl。

Drag/Drop 功能运行良好,可以完成所有应有的工作。当它完成它需要的任何数据操作时,它会将 View Model 的IsModified 属性设置为true。我已验证该值实际上设置为true

问题我遇到的是,当IsModified 属性从我的Drop 方法中更改时,按钮的IsEnabled 属性没有更新;在拖放操作期间将IsModified 设置为true 时,该按钮保持禁用状态。如果我单击该按钮,它会突然更新并启用,需要我再次按下该按钮才能真正按预期进行。

在 ItemsControl 项上的 Drop 事件上调用了 Drop 方法。这是从另一个线程调用的,还是没有通知 UI 属性更改的东西?我已经尝试寻找支持文档,但遇到了一些麻烦。

再一次,设置 IsModified 属性在任何其他情况下都可以继续工作,并正确更新 UI。

有问题的代码相当简单。

XAML:

<ItemsControl.ItemContainerStyle>
    <Style TargetType="ContentPresenter">
        <EventSetter Event="DragEnter" Handler="IcFields_DragEnter"/>
        <EventSetter Event="Drop" Handler="IcFields_Drop"/>
    </Style>
</ItemsControl.ItemContainerStyle>

...
...
...

<Button Margin="5" Padding="10,0,10,0" IsEnabled="{Binding IsModified}"
    Command="{Binding SaveChangesCommand}">Save Changes</Button>

IcFields_Drop 处理程序允许对模型进行更改,最后将IsModified 设置为true

编辑:

这里是一个简短的实现示例。使用上面的 XAML 作为此示例的 XAML。

C# - 代码隐藏

private void IcFields_Drop(object sender, DragEventArgs e)
{
    ViewModel.Drop();   
}

C# - 查看模型

private bool isModified;
public bool IsModified
{
    get { return isModified; }
    set { SetProperty(ref isModified, value); }
}

public void Drop()
{
    //PSEUDO: Do some drag/drop logic for the items attached to the ItemsControl.
    ...
    ...

    IsModified = true;
}

【问题讨论】:

  • 试试这个IsEnabled="{Binding IsModified, UpdateSourceTrigger=PropertyChanged}"
  • @ikerbera 不幸的是,没有成功。
  • IsEnabled="{Binding IsModified, UpdateSourceTrigger=PropertyChanged}, Mode=OneWay"。我通常使用Mode=TwoWay,但在这种情况下感觉有点矫枉过正。看看this
  • @ikerbera Mode=TwoWay 是无稽之谈,因为控件从不主动更新其 IsEnabled 属性,因此没有从目标到源的绑定方向。 UpdateSourceTrigger=PropertyChanged 也毫无意义,因为它只在 TwoWay 或 OneWayToSource Bindings 中起作用。
  • 你的视图模型(因为代码没有显示)是否实现了inotifypropertychanged?

标签: c# wpf data-binding


【解决方案1】:

您应该从命令的CanExecute 方法返回bool,而不是绑定IsEnabled 属性,以指示是否应启用Button。然后,您将调用在您的 Drop() 方法中引发命令的 CanExecuteChanged 事件的方法。

大多数ICommand 实现都包含RaiseCanExecuteChanged() 方法或类似方法,您可以调用这些方法来刷新命令的状态:

public void Drop()
{
    ...
    SaveChangesCommand.RaiseCanExecuteChanged();
}

【讨论】:

  • 这很好。当我真的不需要它时,我绑定了IsEnabled,所以我至少可以丢弃它。我目前在我的实现中没有RaiseCanExecuteChanged() 方法,所以我会看到添加一个。不过,就目前而言,我的 DragDrop 结束时似乎有什么东西正在发生;在单击屏幕上的 anywhere 之前,它不会更新 IsEnabled。调查一下。
  • @pseudorian:例如,你可以看看它是如何在MvvmLight 中实现的。
  • 这对我有用,谢谢!我仍然不确定为什么只有 Drop 事件会导致这个问题,所以我将继续研究它,但至少它可以工作,而且我有一个更好的 ICommand 实现可以使用.
猜你喜欢
  • 2023-03-26
  • 2016-12-17
  • 1970-01-01
  • 2013-07-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-04
  • 2011-03-31
相关资源
最近更新 更多