8

我将主窗口的“WindowState”属性绑定到 ViewModel,以便通过命令更改窗口的状态,但第一次最小化窗口时,它会像 Excel 文件中的工作表一样最小化。是否有解决此问题的方法或将“WindowState”属性绑定到我的 ViewModel 以使窗口正确最小化的正确方法?

4

4 回答 4

21

这是一个使用Relaying Command Logic测试的示例工作。您将获得有关具有模型-视图-视图模型设计模式的 WPF 应用程序的更多详细信息。

<Window x:Class="WpfMvvmTestCSharp.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:vm="clr-namespace:WpfMvvmTestCSharp"
    Title="Window1" Height="300" Width="300" WindowState="{Binding CurWindowState, Mode=TwoWay}">
    <Window.DataContext>
        <vm:Window1ViewModel/>
    </Window.DataContext>
    <Grid>
        <Button Command="{Binding CmdMax}" Height="23" Margin="12,25,0,0" Name="button1" VerticalAlignment="Top" HorizontalAlignment="Left" Width="75">Maximize</Button>
        <Button Command="{Binding CmdMin}" Height="23" Margin="101,25,102,0" Name="button2" VerticalAlignment="Top">Minimize</Button>
        <Button Command="{Binding CmdRes}" Height="23" HorizontalAlignment="Right" Margin="0,25,13,0" Name="button3" VerticalAlignment="Top" Width="75">Restore</Button>
    </Grid>
</Window>

在 Windows ViewModel 中

class Window1ViewModel:ViewModelBase
    {
        public Window1ViewModel()
        {
            CurWindowState = WindowState.Maximized;
        }

        public ICommand CmdMax
        {
            get { return new RelayCommand(param => onCmdMax()); }
        }

        void onCmdMax()
        {
            CurWindowState = WindowState.Maximized;
        }
        public ICommand CmdMin
        {
            get { return new RelayCommand(param => onCmdMin()); }
        }
        void onCmdMin()
        {
            CurWindowState = WindowState.Minimized;
        }
        public ICommand CmdRes
        {
            get { return new RelayCommand(param => onCmdRes()); }
        }

        void onCmdRes()
        {
            CurWindowState = WindowState.Normal;
        }

        private WindowState _curWindowState;
        public WindowState CurWindowState
        {
            get
            {
                return _curWindowState;
            }
            set
            {
                _curWindowState = value;
                base.OnPropertyChanged("CurWindowState");
            }
        }
    }
于 2011-01-13T05:41:10.340 回答
9

我认为您不应该关心视图模型中的窗口状态,这是完全错误的,因为较低级别的层知道较高级别的层(因此是错误的关注点分离(SOC))。

在这种情况下,我通常做的是从包含视图模型的控件或窗口(因此是视图)的代码隐藏中订阅视图模型中的更改。在这种情况下,在代码隐藏中编写代码是有效的,因为它仅在视图中使用(因此代码隐藏是此逻辑的完美位置,您真的不想进行单元测试)。

于 2011-01-13T09:29:34.193 回答
1

另一个要考虑的选项是通过命令和事件订阅后面的代码,例如:

    <Button Command="{Binding SnoozeCommand}" Click="Button_Click">Snooze</Button>

这种情况下的命令会影响 VM。Click 事件,只会改变 Window 的状态。

于 2011-12-12T08:33:55.730 回答
-1

我找到了自己的解决方案,它非常适合 MVVM。我正在使用行为来查找用户控件的父窗口并跟踪 WindowState 更改。

public class WindowStateBehavior : Behavior<UserControl>
{
    public static readonly DependencyProperty WindowStateProperty =
        DependencyProperty.Register(nameof(WindowState), typeof(WindowState), typeof(WindowStateBehavior),
                                    new FrameworkPropertyMetadata(default(WindowState), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

    private Window window;

    public WindowState WindowState
    {
        get => (WindowState) GetValue(WindowStateProperty);
        set => SetCurrentValue(WindowStateProperty, value);
    }

    protected override void OnAttached()
    {
        base.OnAttached();
        this.window = Window.GetWindow(this.AssociatedObject)!;
        this.window.StateChanged += this.OnStateChanged;
    }

    private void OnStateChanged(object sender, EventArgs e) => this.WindowState = this.window.WindowState;
}

这种行为可以在任何像这样的用户控件中使用,在 ViewModel 中具有绑定的 WindowState。

<UserControl x:Class="RCBase.WPF.Monitor.CustomUserView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
         xmlns:behaviors="clr-namespace:RCBase.WPF.Behaviors"
         mc:Ignorable="d" d:DataContext="{d:DesignInstance monitor:CustomUserViewModel}">
<i:Interaction.Behaviors>
    <behaviors:WindowStateBehavior WindowState="{Binding WindowState}" />
</i:Interaction.Behaviors>
于 2021-06-26T05:57:20.190 回答