我有一个基于组合框功能的自定义控件。
下面是简化模板:
<Window x:Class="WpfApplication70.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
WindowStartupLocation="CenterScreen">
<StackPanel>
<Grid>
<ToggleButton Name="PART_DropDownButton"
MinHeight="20"
ClickMode="Release">
<Path x:Name="BtnArrow"
Height="4"
Width="8"
Stretch="Uniform"
Data="F1 M 301.14,-189.041L 311.57,-189.041L 306.355,-182.942L 301.14,-189.041 Z "
Margin="0,0,6,0"
Fill="Black"
HorizontalAlignment="Right" />
</ToggleButton>
<Popup IsOpen="{Binding IsChecked, Mode=TwoWay, ElementName=PART_DropDownButton}"
StaysOpen="False"
MaxHeight="400">
<Ellipse Fill="Red"
Width="50"
Height="50" />
</Popup>
</Grid>
</StackPanel>
</Window>
这似乎有效,因为我可以单击按钮,弹出窗口打开,然后当我在弹出窗口外单击时它会关闭。
但是,我希望在按下按钮时打开弹出窗口,而不是释放按钮。但是,当您在弹出窗口外单击时,将“ClickMode”更改为Press会停止弹出窗口关闭。
我该如何解决这个问题?
答案 0 :(得分:0)
尝试在事件中手动设置Popup的属性IsOpen
:Checked和Unchecked,当Popup关闭时,将ToggleButton.IsChecked
重置为False。
示例:
XAML
<StackPanel>
<Grid>
<ToggleButton Name="PART_DropDownButton"
Checked="PART_DropDownButton_Checked"
Unchecked="PART_DropDownButton_Unchecked">
<Path x:Name="BtnArrow"
Height="4"
Width="8"
Stretch="Uniform"
Data="F1 M 301.14,-189.041L 311.57,-189.041L 306.355,-182.942L 301.14,-189.041 Z "
Margin="0,0,6,0"
Fill="Black"
HorizontalAlignment="Right" />
</ToggleButton>
<Popup Name="MyPopup"
StaysOpen="False"
Closed="MyPopup_Closed"
MaxHeight="400">
<Ellipse Fill="White"
Width="50"
Height="50" />
</Popup>
</Grid>
</StackPanel>
Code-behind
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void MyPopup_Closed(object sender, EventArgs e)
{
if (PART_DropDownButton != Mouse.DirectlyOver)
PART_DropDownButton.IsChecked = false;
}
private void PART_DropDownButton_Checked(object sender, RoutedEventArgs e)
{
MyPopup.IsOpen = true;
}
private void PART_DropDownButton_Unchecked(object sender, RoutedEventArgs e)
{
MyPopup.IsOpen = false;
}
}
答案 1 :(得分:0)
管理通过阅读ComboBox的.net源代码来解决这个问题(没有了解CaptureMode.SubTree,所以也学到了新东西:))。这是一个在实践中显示答案的userControl。
XAML
<UserControl x:Class="WpfApplication74.CustomDropdown"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<ToggleButton Name="PART_DropDownButton"
IsChecked="{Binding IsOpen, Mode=TwoWay, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
MinHeight="20"
HorizontalContentAlignment="Right"
ClickMode="Press">
<Path x:Name="BtnArrow"
Height="4"
Width="8"
Stretch="Uniform"
Data="F1 M 301.14,-189.041L 311.57,-189.041L 306.355,-182.942L 301.14,-189.041 Z "
Margin="0,0,6,0"
Fill="Black" />
</ToggleButton>
<Popup IsOpen="{Binding IsOpen, Mode=TwoWay, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
StaysOpen="False"
MaxHeight="400"
Width="{Binding ActualWidth, ElementName=PART_DropDownButton}"
Opened="OnPopupOpened"
Name="PART_Popup">
<Border BorderThickness="1"
BorderBrush="Black"
Background="#EEE"
Padding="20">
<StackPanel>
<TextBox />
<Slider />
<TextBox />
<Slider />
</StackPanel>
</Border>
</Popup>
</Grid>
代码隐藏
public partial class CustomDropdown : UserControl
{
public bool IsOpen
{
get { return (bool)GetValue(IsOpenProperty); }
set { SetValue(IsOpenProperty, value); }
}
public static readonly DependencyProperty IsOpenProperty =
DependencyProperty.Register("IsOpen", typeof(bool), typeof(CustomDropdown), new PropertyMetadata(false));
public CustomDropdown()
{
InitializeComponent();
}
void OnPopupOpened(object sender, EventArgs e)
{
Mouse.Capture(this, CaptureMode.SubTree);
}
protected override void OnMouseDown(MouseButtonEventArgs e)
{
base.OnMouseDown(e);
if (Mouse.Captured == this && e.OriginalSource == this)
{
SetCurrentValue(CustomDropdown.IsOpenProperty, false);
ReleaseMouseCapture();
}
e.Handled = true;
}
}