Команда обновления пользовательского интерфейса в View Model (WPF) - PullRequest
1 голос
/ 15 марта 2019

Я делаю приложение WPF по шаблону MVVM, где пользователь щелкает элементы дерева (гиперссылки, состоящие из имен цветов, текст имени с соответствующим передним планом), чтобы изменить фон всего окна. Я делаю это с помощью команды relay, но пользовательский интерфейс недопустим в модели представления, где я пишу команду.

Дерево с именами цветов в 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;
}

Команда работала нормально в простом программном коде, но теперь не в модели представления.Помогите пожалуйста?

Ответы [ 2 ]

1 голос
/ 15 марта 2019

this.Background относится к свойству Background вашей модели представления при условии, что метод ChangeColor принадлежит классу модели представления. Чтобы изменить фон окна, необходимо привязать его к свойству Background модели представления и вызвать событие, чтобы сообщить пользовательскому интерфейсу об обновлении. Это требует, чтобы ваша модель представления реализовала событие 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 окна для экземпляра класса модели представления и связать свойство Command Hyperlink следующим образом:

<Hyperlink Command="{Binding DataContext.ColorChangerCommand, RelativeSource={RelativeSource AncestorType=Window}}" 
           Foreground="{Binding Foreground}" TextDecorations="None">
0 голосов
/ 15 марта 2019

Не делайте этого через ViewModel.Пользовательский интерфейс принадлежит View.Используйте поведение для этого.

Если вы связываете ForwardedColor с любым другим элементом управления пользовательского интерфейса, то вы измените свойство привязки этого элемента управления, чтобы вы могли легко управлять им в 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();
    }
}
...