【问题标题】:UI updating command in View Model (WPF)视图模型 (WPF) 中的 UI 更新命令
【发布时间】:2019-08-06 04:37:46
【问题描述】:

我正在制作一个基于 MVVM 模式的 WPF 应用程序,其中用户单击树的项目(由颜色名称组成的超链接,具有相应前景的名称文本)以 更改整个窗口的背景。 我正在通过中继命令执行此操作,但 UI 在我正在编写命令的视图模型中是不可接受的。

XAML 中带有颜色名称的树:

<TreeView Name="tree" ItemSource="{Binding colorList, Mode=TwoWay}" Background="Transparent">
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemSource={Binding Children}>
             <TextBlock><Hyperlink Command={Binding ColorChangerCommand} Foreground={Binding Foreground} TextDecorations="None"><TextBlock Text={Binding Name}/></Hyperlink></TextBlock>
        </HierarchicalDataTemplate>
     </TreeView.ItemTemplate>
 <TreeView>

我的视图模型中的命令:

public RelayCommand ColorChangerCommand{ get; set;}

public TreeViewModel() //Constructor of the View Model
{
   ColorChangerCommand= new RelayCommand(ChangeColor);
}

public void ChangeColor(object sender)
{
  this.Background= (sender as TreeViewItem).Foreground;
}

该命令在简单的代码隐藏中运行良好,但现在不在视图模型中。请帮忙?

【问题讨论】:

  • 你能出示你的约束力声明吗?在 Xaml 中,您正在绑定前景,但在 ViewModel 中,属性被命名为 Background
  • @PraveenM Xaml 中的前景只是必须显示的文本的前景。例如,第一项是“RED”,其前景为红色。在 ViewModel 中的命令中,我得到了单击项目的前景,将其设置为窗口的背景。例如,如果点击红色,窗口的背景也会变成红色。
  • 使用命令时,您在 ChangeColor 函数中获得的对象不是发送者。这仅适用于事件!您应该做的是查看 XAML 触发器,以便您可以按照 WPF 中处理的方式解决您的问题
  • 我同意这有点像您所处的困境,但请考虑以下事项:从您的视图模型中返回一个字符串,即您想要的前景颜色,并在 UI 中使用转换器来创建SolidColorBrush。希望这会有所帮助
  • 应该有一个视图模型项类来表示单个TreeViewItem的数据。该类应该具有背景颜色的 Color 或 Brush 属性,该属性由命令修改。在 TreeView 的 ItemContainerStyle 中,将 TreeViewItem 的 Background 绑定到此视图模型属性。

标签: c# wpf mvvm binding command


【解决方案1】:

this.Background 指的是视图模型的Background 属性,前提是ChangeColor 方法属于视图模型类。要更改窗口的背景,您需要将其绑定到视图模型的Background 属性并引发一个事件来告诉 UI 进行更新。这需要您的视图模型实现INotifyPropertyChanged 事件:

public class ViewModel : INotifyPropertyChanged
{
    public RelayCommand ColorChangerCommand { get; set; }

    public TreeViewModel() //Constructor of the View Model
    {
        ColorChangerCommand = new RelayCommand(ChangeColor);
    }

    public void ChangeColor(object sender)
    {
        this.Background = (sender as TreeViewItem).Foreground;
    }

    private Brush background= Brushes.White;
    public Brush Background
    {
        get { return background; }
        set { Background = value; NotifyPropertyChanged(Background); }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

XAML:

<Window .... Background="{Binding Background}" />

您还需要将窗口的DataContext 设置为您的视图模型类的实例,并像这样绑定Hyperlink 的Command 属性:

<Hyperlink Command="{Binding DataContext.ColorChangerCommand, RelativeSource={RelativeSource AncestorType=Window}}" 
           Foreground="{Binding Foreground}" TextDecorations="None">

【讨论】:

  • public void ChangeColor(object sender) { this.Background = (sender as TreeViewItem).Foreground; } 发件人在这里返回null
  • @BellaSwan:将Hyperlink的CommandParameter绑定到TreeViewItem:CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=TreeViewItem}}"。
  • 现在点击每个项目时背景会变黑,而不是更改为相应的颜色。 :(
  • 什么是“各自的颜色”,即TreeViewItem的Foreground颜色在哪里设置?绑定有效吗?
  • 是的,确实如此。当我为树视图项创建列表时,我添加了前景和名称,然后将其绑定到 XAML 中。例如,单词 RED 以红色显示。所以当我点击它时,作为发件人,它不应该将它的前景色赋予背景,即红色吗?
【解决方案2】:

不要通过 ViewModel 执行此操作。 UI 属于视图。为它使用一种行为。

如果您将ForwardedColor 绑定到任何其他 UI 控件,那么您将更改此控件的绑定属性,以便您可以在 XAML 中轻松管理它。

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
<TextBlock Text="Test" Foreground="Aquamarine">
    <i:Interaction.Behaviors>
        <local:ForwardForegroundOnClick  ForwardedColor="{Binding Background, RelativeSource={RelativeSource AncestorType=Window}, Mode=TwoWay}"/>
    </i:Interaction.Behaviors>
</TextBlock>

public class ForwardForegroundOnClick : Behavior<TextBlock>
{
    public Brush ForwardedColor
    {
        get { return (Brush)GetValue(ForwardedColorProperty); }
        set { SetValue(ForwardedColorProperty, value); }
    }

    // Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ForwardedColorProperty =
        DependencyProperty.Register(nameof(ForwardedColor), typeof(Brush), typeof(ForwardForegroundOnClick), new PropertyMetadata(null));

    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.MouseLeftButtonDown += AssociatedObject_MouseLeftButtonDown;
    }

    private void AssociatedObject_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        ForwardedColor = AssociatedObject.Foreground;
    }

    protected override void OnDetaching()
    {
        AssociatedObject.MouseLeftButtonDown -= AssociatedObject_MouseLeftButtonDown;

        base.OnDetaching();
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-28
    • 2020-01-17
    相关资源
    最近更新 更多