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