C# 在菜单中显示对话框,并防止单击非对话框控件关闭菜单/对话框

C# 在菜单中显示对话框,并防止单击非对话框控件关闭菜单/对话框,c#,wpf,C#,Wpf,我有一个菜单。 单击该项时,我希望子菜单项打开并显示要登录的表单 下面是我已经做的(请随意完全重新设计)。。。 现在的问题是: 当我将鼠标悬停在子项上或单击子项时,该项将高亮显示 当我点击一个项目(文本框除外)时,菜单关闭 谢谢你的帮助 <MenuItem> <MenuItem.Header> <Image Width="16"

我有一个菜单。 单击该项时,我希望子菜单项打开并显示要登录的表单

下面是我已经做的(请随意完全重新设计)。。。 现在的问题是:

  • 当我将鼠标悬停在子项上或单击子项时,该项将高亮显示
  • 当我点击一个项目(文本框除外)时,菜单关闭
谢谢你的帮助

<MenuItem>
            <MenuItem.Header>
                <Image
                    Width="16"
                    Height="16">
                    <Image.Style>
                        <Style TargetType="{x:Type Image}">
                            <Setter Property="Source" Value="{StaticResource DisconnectedIcon}" />
                            <Style.Triggers>
                                <DataTrigger Value="True" Binding="{Binding Connected}">
                                    <Setter Property="Source" Value="{StaticResource ConnectedIcon}"/>
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </Image.Style>
                </Image>
            </MenuItem.Header>
            <autogrid:AutoGrid
                Columns="Auto,Auto"
                Margin="1"
                RowHeight="25">
                <autogrid:AutoGrid.Resources>
                    <Style TargetType="{x:Type TextBox}">
                        <Setter Property="Margin" Value="3" />
                        <Setter Property="Width" Value="100" />
                    </Style>
                    <Style TargetType="{x:Type PasswordBox}">
                        <Setter Property="Margin" Value="3" />
                        <Setter Property="Width" Value="100" />
                    </Style>
                    <Style TargetType="{x:Type TextBlock}">
                        <Setter Property="Margin" Value="3" />
                        <Setter Property="Width" Value="100" />
                    </Style>
                </autogrid:AutoGrid.Resources>
                <TextBlock Text="System: "/>
                <TextBox></TextBox>
                <TextBlock Text="Username: "/>
                <TextBox></TextBox>
                <TextBlock Text="Password: "/>
                <PasswordBox></PasswordBox>
            </autogrid:AutoGrid>
            <Button Content="Connect"/>
        </MenuItem>

我建议将登录控件设置为新窗口的一部分

对于后续的其他人,您需要在Package manager控制台中运行
安装软件包WpfAutoGrid-Version 1.4.0

为了将来的参考,请张贴一个最小和完整的例子。 我花了很长时间才把这件事搞清楚

请阅读

以下是我的MCVE示例:

MainWindow.xaml:

<Window x:Class="WpfApp1.MainWindow"
        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:autogrid="clr-namespace:WpfAutoGrid;assembly=WpfAutoGrid"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="250" Width="500">
    <Window.DataContext>
        <local:VM/>
    </Window.DataContext>
    <DockPanel>
        <Menu DockPanel.Dock="Top">
            <MenuItem>
                <MenuItem.Header>
                    <Image
                    Width="16"
                    Height="16">
                        <Image.Style>
                            <Style TargetType="{x:Type Image}">
                                <Setter Property="Source" Value="{StaticResource DisconnectedIcon}" />
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding Connected}" Value="true">
                                        <Setter Property="Source" Value="{StaticResource ConnectedIcon}"/>
                                    </DataTrigger>
                                    <DataTrigger Binding="{Binding Connected}" Value="false">
                                        <Setter Property="Source" Value="{StaticResource DisconnectedIcon}"/>
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </Image.Style>
                    </Image>
                </MenuItem.Header>
                <MenuItem x:Name="connectMenuItem" Header="{Binding ConnectOrDisconnect}" Click="MenuItem_Click"/>
            </MenuItem>
        </Menu>
        <Grid DockPanel.Dock="Bottom" Background="Black" />
    </DockPanel>
</Window>
<Window x:Class="WpfApp1.ConnectWindow"
        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:autogrid="clr-namespace:WpfAutoGrid;assembly=WpfAutoGrid"
        mc:Ignorable="d" Title="ConnectWindow" Height="180" Width="270">
    <autogrid:AutoGrid            
                    Columns="Auto,Auto"
                    Rows="Auto,Auto, Auto, Auto"
                    Margin="20"
                    RowHeight="25">
        <autogrid:AutoGrid.Resources>
            <Style TargetType="{x:Type TextBox}">
                <Setter Property="Margin" Value="3" />
                <Setter Property="Width" Value="100" />
            </Style>
            <Style TargetType="{x:Type PasswordBox}">
                <Setter Property="Margin" Value="3" />
                <Setter Property="Width" Value="100" />
            </Style>
            <Style TargetType="{x:Type TextBlock}">
                <Setter Property="Margin" Value="3" />
                <Setter Property="Width" Value="100" />
            </Style>
        </autogrid:AutoGrid.Resources>
        <TextBlock Text="System: "/>
        <TextBox></TextBox>
        <TextBlock Text="User Name: "/>
        <TextBox></TextBox>
        <TextBlock Text="Password: "/>
        <PasswordBox></PasswordBox>
        <Button Grid.ColumnSpan="2" Content="Connect" Click="Button_Click" />
    </autogrid:AutoGrid>
</Window>
ConnectWindow.xaml:

<Window x:Class="WpfApp1.MainWindow"
        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:autogrid="clr-namespace:WpfAutoGrid;assembly=WpfAutoGrid"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="250" Width="500">
    <Window.DataContext>
        <local:VM/>
    </Window.DataContext>
    <DockPanel>
        <Menu DockPanel.Dock="Top">
            <MenuItem>
                <MenuItem.Header>
                    <Image
                    Width="16"
                    Height="16">
                        <Image.Style>
                            <Style TargetType="{x:Type Image}">
                                <Setter Property="Source" Value="{StaticResource DisconnectedIcon}" />
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding Connected}" Value="true">
                                        <Setter Property="Source" Value="{StaticResource ConnectedIcon}"/>
                                    </DataTrigger>
                                    <DataTrigger Binding="{Binding Connected}" Value="false">
                                        <Setter Property="Source" Value="{StaticResource DisconnectedIcon}"/>
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </Image.Style>
                    </Image>
                </MenuItem.Header>
                <MenuItem x:Name="connectMenuItem" Header="{Binding ConnectOrDisconnect}" Click="MenuItem_Click"/>
            </MenuItem>
        </Menu>
        <Grid DockPanel.Dock="Bottom" Background="Black" />
    </DockPanel>
</Window>
<Window x:Class="WpfApp1.ConnectWindow"
        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:autogrid="clr-namespace:WpfAutoGrid;assembly=WpfAutoGrid"
        mc:Ignorable="d" Title="ConnectWindow" Height="180" Width="270">
    <autogrid:AutoGrid            
                    Columns="Auto,Auto"
                    Rows="Auto,Auto, Auto, Auto"
                    Margin="20"
                    RowHeight="25">
        <autogrid:AutoGrid.Resources>
            <Style TargetType="{x:Type TextBox}">
                <Setter Property="Margin" Value="3" />
                <Setter Property="Width" Value="100" />
            </Style>
            <Style TargetType="{x:Type PasswordBox}">
                <Setter Property="Margin" Value="3" />
                <Setter Property="Width" Value="100" />
            </Style>
            <Style TargetType="{x:Type TextBlock}">
                <Setter Property="Margin" Value="3" />
                <Setter Property="Width" Value="100" />
            </Style>
        </autogrid:AutoGrid.Resources>
        <TextBlock Text="System: "/>
        <TextBox></TextBox>
        <TextBlock Text="User Name: "/>
        <TextBox></TextBox>
        <TextBlock Text="Password: "/>
        <PasswordBox></PasswordBox>
        <Button Grid.ColumnSpan="2" Content="Connect" Click="Button_Click" />
    </autogrid:AutoGrid>
</Window>
VM.cs:

using System.ComponentModel;

namespace WpfApp1
{
    class VM : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private bool connected; 
        public bool Connected
        {
            get { return connected; }
            set
            {
                {
                    connected = value;
                    OnPropertyChanged("Connected");
                    if (value) { ConnectOrDisconnect = "Disconnect"; }
                    else { ConnectOrDisconnect = "Connect"; }
                }
            }
        }

        private string connectOrDisconnect;
        public string ConnectOrDisconnect
        {
            get { return connectOrDisconnect; }
            set
            {
                connectOrDisconnect = value;
                OnPropertyChanged("ConnectOrDisconnect");
            }
        }

        public VM()
        {
            Connected = false;
        }

        protected void OnPropertyChanged(string name)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
    }
}
App.xaml:

<Application x:Class="WpfApp1.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="resources.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

resources.xaml:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <BitmapImage x:Key="ConnectedIcon" UriSource="pack://application:,,,/WpfApp1;component/ConnectedIcon.ico" />
    <BitmapImage x:Key="DisconnectedIcon" UriSource="pack://application:,,,/WpfApp1;component/DisconnectedIcon.ico" />
</ResourceDictionary>

我建议将登录控件设置为新窗口的一部分

对于后续的其他人,您需要在Package manager控制台中运行
安装软件包WpfAutoGrid-Version 1.4.0

为了将来的参考,请张贴一个最小和完整的例子。 我花了很长时间才把这件事搞清楚

请阅读

以下是我的MCVE示例:

MainWindow.xaml:

<Window x:Class="WpfApp1.MainWindow"
        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:autogrid="clr-namespace:WpfAutoGrid;assembly=WpfAutoGrid"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="250" Width="500">
    <Window.DataContext>
        <local:VM/>
    </Window.DataContext>
    <DockPanel>
        <Menu DockPanel.Dock="Top">
            <MenuItem>
                <MenuItem.Header>
                    <Image
                    Width="16"
                    Height="16">
                        <Image.Style>
                            <Style TargetType="{x:Type Image}">
                                <Setter Property="Source" Value="{StaticResource DisconnectedIcon}" />
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding Connected}" Value="true">
                                        <Setter Property="Source" Value="{StaticResource ConnectedIcon}"/>
                                    </DataTrigger>
                                    <DataTrigger Binding="{Binding Connected}" Value="false">
                                        <Setter Property="Source" Value="{StaticResource DisconnectedIcon}"/>
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </Image.Style>
                    </Image>
                </MenuItem.Header>
                <MenuItem x:Name="connectMenuItem" Header="{Binding ConnectOrDisconnect}" Click="MenuItem_Click"/>
            </MenuItem>
        </Menu>
        <Grid DockPanel.Dock="Bottom" Background="Black" />
    </DockPanel>
</Window>
<Window x:Class="WpfApp1.ConnectWindow"
        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:autogrid="clr-namespace:WpfAutoGrid;assembly=WpfAutoGrid"
        mc:Ignorable="d" Title="ConnectWindow" Height="180" Width="270">
    <autogrid:AutoGrid            
                    Columns="Auto,Auto"
                    Rows="Auto,Auto, Auto, Auto"
                    Margin="20"
                    RowHeight="25">
        <autogrid:AutoGrid.Resources>
            <Style TargetType="{x:Type TextBox}">
                <Setter Property="Margin" Value="3" />
                <Setter Property="Width" Value="100" />
            </Style>
            <Style TargetType="{x:Type PasswordBox}">
                <Setter Property="Margin" Value="3" />
                <Setter Property="Width" Value="100" />
            </Style>
            <Style TargetType="{x:Type TextBlock}">
                <Setter Property="Margin" Value="3" />
                <Setter Property="Width" Value="100" />
            </Style>
        </autogrid:AutoGrid.Resources>
        <TextBlock Text="System: "/>
        <TextBox></TextBox>
        <TextBlock Text="User Name: "/>
        <TextBox></TextBox>
        <TextBlock Text="Password: "/>
        <PasswordBox></PasswordBox>
        <Button Grid.ColumnSpan="2" Content="Connect" Click="Button_Click" />
    </autogrid:AutoGrid>
</Window>
ConnectWindow.xaml:

<Window x:Class="WpfApp1.MainWindow"
        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:autogrid="clr-namespace:WpfAutoGrid;assembly=WpfAutoGrid"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="250" Width="500">
    <Window.DataContext>
        <local:VM/>
    </Window.DataContext>
    <DockPanel>
        <Menu DockPanel.Dock="Top">
            <MenuItem>
                <MenuItem.Header>
                    <Image
                    Width="16"
                    Height="16">
                        <Image.Style>
                            <Style TargetType="{x:Type Image}">
                                <Setter Property="Source" Value="{StaticResource DisconnectedIcon}" />
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding Connected}" Value="true">
                                        <Setter Property="Source" Value="{StaticResource ConnectedIcon}"/>
                                    </DataTrigger>
                                    <DataTrigger Binding="{Binding Connected}" Value="false">
                                        <Setter Property="Source" Value="{StaticResource DisconnectedIcon}"/>
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </Image.Style>
                    </Image>
                </MenuItem.Header>
                <MenuItem x:Name="connectMenuItem" Header="{Binding ConnectOrDisconnect}" Click="MenuItem_Click"/>
            </MenuItem>
        </Menu>
        <Grid DockPanel.Dock="Bottom" Background="Black" />
    </DockPanel>
</Window>
<Window x:Class="WpfApp1.ConnectWindow"
        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:autogrid="clr-namespace:WpfAutoGrid;assembly=WpfAutoGrid"
        mc:Ignorable="d" Title="ConnectWindow" Height="180" Width="270">
    <autogrid:AutoGrid            
                    Columns="Auto,Auto"
                    Rows="Auto,Auto, Auto, Auto"
                    Margin="20"
                    RowHeight="25">
        <autogrid:AutoGrid.Resources>
            <Style TargetType="{x:Type TextBox}">
                <Setter Property="Margin" Value="3" />
                <Setter Property="Width" Value="100" />
            </Style>
            <Style TargetType="{x:Type PasswordBox}">
                <Setter Property="Margin" Value="3" />
                <Setter Property="Width" Value="100" />
            </Style>
            <Style TargetType="{x:Type TextBlock}">
                <Setter Property="Margin" Value="3" />
                <Setter Property="Width" Value="100" />
            </Style>
        </autogrid:AutoGrid.Resources>
        <TextBlock Text="System: "/>
        <TextBox></TextBox>
        <TextBlock Text="User Name: "/>
        <TextBox></TextBox>
        <TextBlock Text="Password: "/>
        <PasswordBox></PasswordBox>
        <Button Grid.ColumnSpan="2" Content="Connect" Click="Button_Click" />
    </autogrid:AutoGrid>
</Window>
VM.cs:

using System.ComponentModel;

namespace WpfApp1
{
    class VM : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private bool connected; 
        public bool Connected
        {
            get { return connected; }
            set
            {
                {
                    connected = value;
                    OnPropertyChanged("Connected");
                    if (value) { ConnectOrDisconnect = "Disconnect"; }
                    else { ConnectOrDisconnect = "Connect"; }
                }
            }
        }

        private string connectOrDisconnect;
        public string ConnectOrDisconnect
        {
            get { return connectOrDisconnect; }
            set
            {
                connectOrDisconnect = value;
                OnPropertyChanged("ConnectOrDisconnect");
            }
        }

        public VM()
        {
            Connected = false;
        }

        protected void OnPropertyChanged(string name)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
    }
}
App.xaml:

<Application x:Class="WpfApp1.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="resources.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

resources.xaml:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <BitmapImage x:Key="ConnectedIcon" UriSource="pack://application:,,,/WpfApp1;component/ConnectedIcon.ico" />
    <BitmapImage x:Key="DisconnectedIcon" UriSource="pack://application:,,,/WpfApp1;component/DisconnectedIcon.ico" />
</ResourceDictionary>


可能重复的@Sinatr I验证了由于某种原因设置此属性并不能解决babbelut的问题。也许是因为WpfAutoGrid处理事件的方式…?可能是@Sinatr的重复我验证了设置此属性并不能解决babbelut的问题,原因是。也许是因为WpfAutoGrid处理事件的方式。。?