gpt4 book ai didi

c# - 在 MVVM 中给出一些命令来查看

转载 作者:可可西里 更新时间:2023-11-01 03:12:07 24 4
gpt4 key购买 nike

让我们假设我有一些用户控制。用户控件有一些子窗口。用户控制用户想要关闭某种类型的子窗口。后面的用户控制代码中有一个方法:

public void CloseChildWindows(ChildWindowType type)
{
...
}

但我无法调用此方法,因为我无法直接访问 View 。

我想到的另一个解决方案是以某种方式将用户控件 ViewModel 公开为其属性之一(这样我就可以绑定(bind)它并直接向 ViewModel 发出命令)。但是我不希望用户控制用户知道任何关于用户控制 ViewModel 的信息。

那么解决这个问题的正确方法是什么?

最佳答案

我觉得我刚刚找到了一个相当不错的 MVVM 解决方案来解决这个问题。我编写了一个公开类型属性 WindowType 和 bool 属性 Open 的行为。 DataBinding 后者允许 ViewModel 轻松打开和关闭窗口,而无需了解有关 View 的任何信息。

一定要爱行为... :)

enter image description here

Xaml:

<UserControl x:Class="WpfApplication1.OpenCloseWindowDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApplication1"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">

<UserControl.DataContext>
<local:ViewModel />
</UserControl.DataContext>
<i:Interaction.Behaviors>
<!-- TwoWay binding is necessary, otherwise after user closed a window directly, it cannot be opened again -->
<local:OpenCloseWindowBehavior WindowType="local:BlackWindow" Open="{Binding BlackOpen, Mode=TwoWay}" />
<local:OpenCloseWindowBehavior WindowType="local:YellowWindow" Open="{Binding YellowOpen, Mode=TwoWay}" />
<local:OpenCloseWindowBehavior WindowType="local:PurpleWindow" Open="{Binding PurpleOpen, Mode=TwoWay}" />
</i:Interaction.Behaviors>
<UserControl.Resources>
<Thickness x:Key="StdMargin">5</Thickness>
<Style TargetType="Button" >
<Setter Property="MinWidth" Value="60" />
<Setter Property="Margin" Value="{StaticResource StdMargin}" />
</Style>
<Style TargetType="Border" >
<Setter Property="Margin" Value="{StaticResource StdMargin}" />
</Style>
</UserControl.Resources>

<Grid>
<StackPanel>
<StackPanel Orientation="Horizontal">
<Border Background="Black" Width="30" />
<Button Content="Open" Command="{Binding OpenBlackCommand}" CommandParameter="True" />
<Button Content="Close" Command="{Binding OpenBlackCommand}" CommandParameter="False" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<Border Background="Yellow" Width="30" />
<Button Content="Open" Command="{Binding OpenYellowCommand}" CommandParameter="True" />
<Button Content="Close" Command="{Binding OpenYellowCommand}" CommandParameter="False" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<Border Background="Purple" Width="30" />
<Button Content="Open" Command="{Binding OpenPurpleCommand}" CommandParameter="True" />
<Button Content="Close" Command="{Binding OpenPurpleCommand}" CommandParameter="False" />
</StackPanel>
</StackPanel>
</Grid>
</UserControl>

YellowWindow(类似黑色/紫色):

<Window x:Class="WpfApplication1.YellowWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="YellowWindow" Height="300" Width="300">
<Grid Background="Yellow" />
</Window>

View 模型、 Action 命令:

using System;
using System.ComponentModel;
using System.Windows.Input;

namespace WpfApplication1
{
public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}

private bool _blackOpen;
public bool BlackOpen { get { return _blackOpen; } set { _blackOpen = value; OnPropertyChanged("BlackOpen"); } }

private bool _yellowOpen;
public bool YellowOpen { get { return _yellowOpen; } set { _yellowOpen = value; OnPropertyChanged("YellowOpen"); } }

private bool _purpleOpen;
public bool PurpleOpen { get { return _purpleOpen; } set { _purpleOpen = value; OnPropertyChanged("PurpleOpen"); } }

public ICommand OpenBlackCommand { get; private set; }
public ICommand OpenYellowCommand { get; private set; }
public ICommand OpenPurpleCommand { get; private set; }


public ViewModel()
{
this.OpenBlackCommand = new ActionCommand<bool>(OpenBlack);
this.OpenYellowCommand = new ActionCommand<bool>(OpenYellow);
this.OpenPurpleCommand = new ActionCommand<bool>(OpenPurple);
}

private void OpenBlack(bool open) { this.BlackOpen = open; }
private void OpenYellow(bool open) { this.YellowOpen = open; }
private void OpenPurple(bool open) { this.PurpleOpen = open; }

}

public class ActionCommand<T> : ICommand
{
public event EventHandler CanExecuteChanged;
private Action<T> _action;

public ActionCommand(Action<T> action)
{
_action = action;
}

public bool CanExecute(object parameter) { return true; }

public void Execute(object parameter)
{
if (_action != null)
{
var castParameter = (T)Convert.ChangeType(parameter, typeof(T));
_action(castParameter);
}
}
}
}

打开关闭窗口行为:

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;

namespace WpfApplication1
{
public class OpenCloseWindowBehavior : Behavior<UserControl>
{
private Window _windowInstance;

public Type WindowType { get { return (Type)GetValue(WindowTypeProperty); } set { SetValue(WindowTypeProperty, value); } }
public static readonly DependencyProperty WindowTypeProperty = DependencyProperty.Register("WindowType", typeof(Type), typeof(OpenCloseWindowBehavior), new PropertyMetadata(null));

public bool Open { get { return (bool)GetValue(OpenProperty); } set { SetValue(OpenProperty, value); } }
public static readonly DependencyProperty OpenProperty = DependencyProperty.Register("Open", typeof(bool), typeof(OpenCloseWindowBehavior), new PropertyMetadata(false, OnOpenChanged));

/// <summary>
/// Opens or closes a window of type 'WindowType'.
/// </summary>
private static void OnOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var me = (OpenCloseWindowBehavior)d;
if ((bool)e.NewValue)
{
object instance = Activator.CreateInstance(me.WindowType);
if (instance is Window)
{
Window window = (Window)instance;
window.Closing += (s, ev) =>
{
if (me.Open) // window closed directly by user
{
me._windowInstance = null; // prevents repeated Close call
me.Open = false; // set to false, so next time Open is set to true, OnOpenChanged is triggered again
}
};
window.Show();
me._windowInstance = window;
}
else
{
// could check this already in PropertyChangedCallback of WindowType - but doesn't matter until someone actually tries to open it.
throw new ArgumentException(string.Format("Type '{0}' does not derive from System.Windows.Window.", me.WindowType));
}
}
else
{
if (me._windowInstance != null)
me._windowInstance.Close(); // closed by viewmodel
}
}
}
}

关于c# - 在 MVVM 中给出一些命令来查看,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15465161/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com