【问题标题】:RxUI - WPF - Style DataTrigger binding with no DataContextRxUI - WPF - 没有 DataContext 的样式 DataTrigger 绑定
【发布时间】:2019-04-29 16:22:02
【问题描述】:

警告:
全新的 ReactiveUI。试图完全使用 RxUI,目的是从不设置视图的 DataContext。我相信这是可以做到的!

场景:
我有一个按钮,该按钮有一个样式,该按钮的样式有一个 MultiDataTrigger,第一个条件是 IsMouseOver,第二个条件是我的 bool 类型的 ViewModel 上的属性。然后这会改变按钮的背景或前景。传统上,您只需将第二个条件绑定到 ViewModel 的属性。

是否有一种可行的方法让这种交互在不使用 DataContext 的情况下工作,但仍然具有我期望的相同结果?我无法直接访问条件绑定,因为它没有名称。所以必须有一些奇怪的设置才能让它工作。

解决方案不太喜欢:
我可能会添加一个不可见的控件,为其命名,然后使用 this.OneWayBind() 将该属性绑定到该控件的“IsEnabled”属性。这样做时,按钮的 MultiDataTrigger 的第二个条件可以使用基于 ElementName 及其 IsEnabled 路径的绑定。这将允许我不使用 DataContext 但对我的口味来说似乎太“hacky”了。一定有别的办法!

提前致谢!

编辑 1 - 根据 Glenn Watson 对帖子的评论尝试 1

        this.WhenActivated(disposables =>
        {
            this.WhenAnyValue(x => x.TheButton.IsMouseOver, x => x.ViewModel.SomeBoolValue).Subscribe(x =>
            {
                if (!x.Item1)
                    TheButton.Background = x.Item2 ? Brushes.Gray : Brushes.Blue;
                else
                    TheButton.Background = x.Item2 ? Brushes.Red : Brushes.Green;
            }).DisposeWith(disposables);
        });

Edit 2 - 实施/使用 Glenn Watson 的回答。

【问题讨论】:

  • 您可以使用 ReactiveUI.Events.WPF nuget 包,获取 MouseOver observable,并使用 Observable.CombineLatest() 和 ViewModel 中的 WhenAnyValue(),并使用 BindTo() 方法我我猜。
  • 我很怀疑所有反对这个问题的人都是传统的 WPF 开发人员,并不真正熟悉 RxUI 样式绑定。
  • @GlennWatson RE:第一反应:几乎成功了,但它让我朝着正确的方向前进! UIElement MouseOver 没有事件,也没有后续的 Events.WPF Observable。我得到的最接近的是 UIElement 的IsMouseDirectlyOverChanged。根据微软的言论,这个名字是骗人的。相反,我在 IsMouseOver 的按钮上使用了 WhenAnyValue。我编辑了帖子。对于使用更多 ReactiveUI 的更好解决方案有什么建议吗?
  • @GlennWatson RE:第二个回应:我也被否决票吓了一跳。我想也许是因为我没有包含实际的代码来工作,也许我的问题太模糊了,或者我是一个新手,应该知道该怎么做。我很高兴我没有用 MVVM 标记它,因为最纯粹的人会进行猎巫。作为曾经通过安全类型和 ReactiveUI 恢复的最纯粹的 MVVM,我知道不要让他们参与其中!感谢格伦的所有帮助!

标签: c# wpf reactiveui multidatatrigger


【解决方案1】:

我有几个想法。没有时间先尝试它们,但它们可能会有所帮助。

  1. 您可以尝试将触发器直接嵌入到按钮的资源中,然后仍将按钮名称用于 onewaybind。

  2. 您可以尝试为按钮定义一个新的 DataTemplate 并定位具有触发器属性的视图模型。

【讨论】:

  • 1.我假设您的意思是创建一个 TriggerBase 对象并将其添加到按钮的触发器中,纯粹是在后面的代码中? 2. 这种方法是为特定于该交互部分的 DataTemplate 创建视图和 ViewModel 并通过其 ViewModel 属性绑定?当然..这一切都是可行的,但是要完成曾经如此简单的事情需要做很多工作。我倾向于使用按钮的 Tag 属性绑定到 ViewModel 的属性。
  • 我已经多次以这种方式使用Tag来完成各种事情。仍然使用它来将值传递给我的虚拟键盘。但实际上我的意思是将样式直接添加到按钮的 xaml 而不是后面的代码。无论哪种方式,我都很想知道最终会发生什么。
【解决方案2】:

我会推荐一些接近你所拥有的解决方案的东西:

this.WhenAnyValue(x => x.TheButton.IsMouseOver, x => x.ViewModel.SomeBoolValue,
      (isMouseOver, boolValue) => 
      {
         if (isMouseOver)
           return boolValue ? Brushes.Gray : Brushes.Blue;
         else 
           return boolValue ? Brushes.Red : Brushes.Green;
      })
      .BindTo(this, view => view.TheButton.Background)
      .DisposeWith(disposables);

修改是使用第三个参数,它将参数化的 lambda 接收到前两个值,然后只使用 BindTo()。它不应该与你所拥有的那么不同。

【讨论】:

  • 没想到看其他参数选项。仍然围绕着 ReactiveUI 概念,所以我非常依赖网络上的示例。不幸的是,许多示例使用了现在已弃用的东西,因此必须将某些场景拼凑在一起。再次感谢格伦!
  • 顺便说一句,请随意跳入 RxUI slack 频道,我们随时为您提供帮助,如果文档网站上有任何不推荐使用的示例,请随时在 github.com/reactiveui/website 上打开问题
猜你喜欢
  • 2013-10-19
  • 2013-07-10
  • 2016-10-28
  • 1970-01-01
  • 2015-06-29
  • 2013-06-04
  • 2011-10-09
  • 1970-01-01
  • 2012-12-06
相关资源
最近更新 更多