C# 在WPF中,使用按钮和弹出窗口构建用户控件,以及如何在单击菜单项时隐藏弹出窗口?

C# 在WPF中,使用按钮和弹出窗口构建用户控件,以及如何在单击菜单项时隐藏弹出窗口?,c#,wpf,mvvm,user-controls,popup,C#,Wpf,Mvvm,User Controls,Popup,我正在构建一个名为MenuPopup的用户控件。我在MVVM项目中使用这个控件 它是这样的: 但是现在,我没有理想的方法在单击一个菜单项后隐藏弹出窗口。如果通过菜单项的单击事件隐藏它,那么如何将命令绑定到ViewModel以处理业务逻辑 <!--MenuPopup.xaml--> <UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="ht

我正在构建一个名为
MenuPopup
的用户控件。我在MVVM项目中使用这个控件

它是这样的:

但是现在,我没有理想的方法在单击一个菜单项后隐藏弹出窗口。如果通过菜单项的单击事件隐藏它,那么如何将命令绑定到ViewModel以处理业务逻辑

<!--MenuPopup.xaml-->
<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
    mc:Ignorable="d"
    x:Class="WpfApplication10.MenuPopup"
    x:Name="UserControl">

    <UserControl.Resources>
        <Style x:Key="ButtonFocusVisual">
            <Setter Property="Control.Template">
                <Setter.Value>
                    <ControlTemplate>
                        <Rectangle Margin="2" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <LinearGradientBrush x:Key="ButtonNormalBackground" EndPoint="0,1" StartPoint="0,0">
            <GradientStop Color="#F3F3F3" Offset="0"/>
            <GradientStop Color="#EBEBEB" Offset="0.5"/>
            <GradientStop Color="#DDDDDD" Offset="0.5"/>
            <GradientStop Color="#CDCDCD" Offset="1"/>
        </LinearGradientBrush>
        <SolidColorBrush x:Key="ButtonNormalBorder" Color="#FF707070"/>

        <Geometry x:Key="ArrowGraph">M 3,6 L 13,6 L 8,12 Z</Geometry>
        <Geometry x:Key="LineGraph" >M 12.3,7 L 9,11</Geometry>

        <Style x:Key="ArrowMenuButtonStyle" TargetType="{x:Type Button}">
            <Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}"/>
            <Setter Property="Background" Value="#00FFFFFF"/>
            <Setter Property="BorderBrush" Value="#FFFFFFFF"/>
            <Setter Property="BorderThickness" Value="1"/>
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
            <Setter Property="HorizontalContentAlignment" Value="Center"/>
            <Setter Property="VerticalContentAlignment" Value="Center"/>
            <Setter Property="Padding" Value="1"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <Grid>
                            <Border BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" BorderThickness="1"/>
                            <Path x:Name="ArrowPath" Data="{StaticResource ArrowGraph}" Fill="#FFFFFFFF"/>
                            <Path x:Name="LinePath" Data="{StaticResource LineGraph}" Fill="#FFD5D5D5" />
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsKeyboardFocused" Value="true"/>
                            <Trigger Property="ToggleButton.IsChecked" Value="true"/>
                            <Trigger Property="IsEnabled" Value="false">
                                <Setter Property="Foreground" Value="#ADADAD"/>
                            </Trigger>
                            <Trigger Property="IsMouseOver" Value="true">
                                <Setter Property="Background"  Value="#FF219266"/>
                                <Setter Property="BorderBrush" Value="#FF167559"/>
                                <Setter Property="Fill" TargetName="LinePath" Value="#FF1E7B57"/>
                            </Trigger>
                            <Trigger Property="IsPressed" Value="true">
                                <Setter Property="Background"  Value="#FF219266"/>
                                <Setter Property="BorderBrush" Value="#FF7ABEA3"/>
                                <Setter Property="Fill" TargetName="LinePath" Value="#FF1E7B57"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </UserControl.Resources>

    <Grid x:Name="LayoutRoot">
        <Grid>
            <Button x:Name="MenuButton" Click="MenuButton_Click" Content="" Width="16" Height="16" BorderThickness="0" Padding="0" Style="{DynamicResource ArrowMenuButtonStyle}" />
            <Popup x:Name="MenuButtonPopup" StaysOpen="False" PlacementTarget="{Binding ElementName=MenuButton}" >
                <Grid>
                    <Border Background="White">
                        <StackPanel >
                            <MenuItem Header="XX1" />
                            <MenuItem Header="XX2" />
                        </StackPanel>
                    </Border>
                </Grid>
            </Popup>
        </Grid>
    </Grid>
</UserControl>

您可以将viewmodel上的bool属性设置为IsPopupOpen,并将Popup.IsOpen绑定到此属性。现在,将按钮命令绑定到ViewModel中定义的命令,并将commandhandler中的IsPopupOpen设置为false


谢谢

如果您是这样要求的,您可以使用
命令绑定
将事件路由到视图模型。哦,我应该尝试使用click事件处理程序和commandbinding。我同时使用click事件和命令,效果很好。我只是认为隐藏弹出窗口可以在视图层中处理。如果我的观点是错误的,请告诉我,我只是一个新手。你在使用MVVM吗,即你是否有ViewModel支持你的视图(userControl)?在MVVM中,我使用userControl中的Commond绑定按钮到MainViewModel(因为主界面中使用了userControl)并处理一些业务逻辑。我是否应该创建一个专用的ViewModel以用于UserControl?这就是我要说的,您可以在MainViewModel中拥有另一个属性,并将其绑定到IsPopupOpen,并在button命令的命令处理程序中将IsPopupOpen设置为false。将绑定模式设置为双向
// MenuPopup.xaml.cs
namespace WpfApplication10
{
    /// <summary>
    /// Interaction logic for MenuPopup.xaml
    /// </summary>
    public partial class MenuPopup : UserControl
    {

        public MenuPopup()
        {
            this.InitializeComponent();
        }

        private void MenuButton_Click(object sender, RoutedEventArgs e)
        {
            MenuButtonPopup.IsOpen = true;
        }
    }
}
<!--parts in MenuPopup.xaml -->
<Grid x:Name="LayoutRoot">
    <Button x:Name="MenuButton" Click="MenuButton_Click" Content="" Width="16" Height="16" BorderThickness="0" Padding="0" Style="{DynamicResource ArrowMenuButtonStyle}" />
    <Popup x:Name="MenuButtonPopup" StaysOpen="False" PlacementTarget="{Binding ElementName=MenuButton}" >
        <Grid>
            <Border Background="White">
                <StackPanel >
                    <MenuItem Header="XX1" Click="MenuItem_Click" Command="{Binding IncreaseCommand}"/>
                    <MenuItem Header="XX2" Click="MenuItem_Click" />
                </StackPanel>
            </Border>
        </Grid>
    </Popup>
</Grid>
// MenuPopup.xaml.cs
namespace WpfApplication10
{
    /// <summary>
    /// Interaction logic for MenuPopup.xaml
    /// </summary>
    public partial class MenuPopup : UserControl
    {

        public MenuPopup()
        {
            this.InitializeComponent();
        }

        private void MenuButton_Click(object sender, RoutedEventArgs e)
        {
            MenuButtonPopup.IsOpen = true;
        }

        private void MenuItem_Click(object sender, RoutedEventArgs e)
        {
            MenuButtonPopup.IsOpen = false;
        }
    }
}
// MainViewModel.cs
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;

namespace WpfApplication10.ViewModel
{
    public class MainViewModel : ViewModelBase
    {
        public MainViewModel()
        {
            IncreaseCommand = new RelayCommand(() => ++Cnt);
        }

        private int cnt = 0;
        public int Cnt
        {
            get { return cnt; }
            set { cnt = value; RaisePropertyChanged("Cnt"); }
        }

        private RelayCommand increaseCommand;
        public RelayCommand IncreaseCommand { get; private set; }
    }
}