我是WPF和XAML的新手,无法在这里找到我做错的事。
我的UserControl
控件很少,我需要从代码隐藏中控制Popup.IsOpen
。
public bool PopupVisible
{
get
{
//true
if( txtSearch.IsKeyboardFocusWithin ) return true;
if( txtSearch.IsMouseOver ) return true;
//false
if( txtSearch.IsKeyboardFocusWithin == false &&
( grid.IsMouseOver == false || popContainer.IsMouseOver == false || popContainer.IsMouseOver == false)
)
{
return false;
}
return false;
}
}
我的XAML:
<UserControl x:Class="Controls.KlasifikacijaBolestSearchBox.KlasifikacijaBolestSearchBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:controls="clr-namespace:Controls"
xmlns:itemClass="clr-namespace:Controls.KlasifikacijaBolestSearchBox.ViewModels"
x:Name="this"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" Loaded="this_Loaded">
<Grid x:Name="grid" DataContext="{Binding Class}">
<DockPanel LastChildFill="False">
<controls:SearchTextBox x:Name="txtSearch" DockPanel.Dock="Top" TextChanged="txtSearch_TextChanged" OnSearch="txtSearch_OnSearch" Background="WhiteSmoke"></controls:SearchTextBox>
</DockPanel>
<Popup x:Name="popContainer"
Placement="Bottom"
PlacementTarget="{Binding ElementName=txtSearch}"
AllowsTransparency="True"
StaysOpen="True"
IsOpen="{Binding PopupVisible, Mode=TwoWay}"
PopupAnimation="Fade"
MinWidth="500"
MinHeight="500"
Width="{Binding ElementName=txtSearch, Path=ActualWidth}">
<DockPanel LastChildFill="True">
<TextBlock DockPanel.Dock="Top" TextAlignment="Center" Text="Klasifikacija bolesti" FontWeight="Bold" Background="{DynamicResource WindowBackgroundBrush}" Foreground="White">
</TextBlock>
<TreeView
DockPanel.Dock="Top"
x:Name="tvKlasifikacijaBolest"
ItemTemplate="{StaticResource tvKlasifikacijaBolestHDStyle}"
ItemContainerStyle="{StaticResource tvKlasifikacijaBolestItemStyle}"
ScrollViewer.CanContentScroll="True"
ScrollViewer.VerticalScrollBarVisibility="Visible"
MouseDoubleClick="tvKlasifikacijaBolest_MouseDoubleClick">
</TreeView>
</DockPanel>
</Popup>
</Grid>
</UserControl>
然后我想我需要实现INotifyPropertyChanged
所以我将代码更改为:
private bool popupOpen;
public bool PopupOpen
{
get { return popupOpen; }
set
{
popupOpen = value;
OnNotifyPropertyChanged("PopupOpen");
}
}
private void txtSearch_TextChanged(string searchText, string searchType)
{
PopupOpen = true;
}
当然改变了我的XAML部分:
<Popup x:Name="popContainer"
IsOpen="{Binding PopupOpen, Mode=TwoWay}">
<!-- ... -->
</Popup>
我的弹出窗口永远不会被打开。
起初我使用了数据触发器并且它工作正常,直到我转向AllowTransparency="True"
然后我的触发器有一些问题当我将鼠标移到我的控件上时poup的某些部分是透明的并且它关闭弹出窗口因此我改为代码隐藏但我不知道我做错了什么。
底线是 - 我需要在txtSearch.IsMouseOver
或IsKeyboardFocusedWithin
或我的树视图IsMouseOver
或弹出控件IsMouseOver = true
中的任何子组件(边框,标签,文本块...)。
如果txtSearch
具有焦点,那么如果IsMouseOver
元素上的Popup
为True
或False
,则弹出窗口需要保持打开状态。
答案 0 :(得分:3)
你有两个问题。
注意:以下两段仅用于教育目的。
第一个。 PopupVisible
从未通知它已更改。要通知目标,您需要对其进行更改,使其成为只读DependencyPrperty
:
private static readonly DependencyPropertyKey IsPopupOpenPropertyKey = DependencyProperty.RegisterReadOnly(
"IsPopupOpen",
typeof(bool),
typeof(MainWindow),
new FrameworkPropertyMetadata(false)
);
private static readonly DependencyProperty IsPopupOpenProperty = IsPopupOpenPropertyKey.DependencyProperty;
public bool IsPopupOpen
{
get { return (bool)GetValue(IsPopupOpenProperty); }
private set { SetValue(IsPopupOpenPropertyKey, value); }
}
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
if (e.Property == UIElement.IsMouseOverProperty ||
e.Property == UIElement.IsKeyboardFocusWithinProperty)
{
IsPopupOpen =
txtSearch.IsMouseOver ||
txtSearch.IsKeyboardFocusWithin;
}
}
第二个。当您绑定到控件的属性时,您必须指定ElementName
或RelativeSource
。否则,Binding
将在继承的数据上下文中查看该属性。
<UserControl x:Class="Controls.KlasifikacijaBolestSearchBox.KlasifikacijaBolestSearchBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:searchBox="Controls.KlasifikacijaBolestSearchBox">
<!-- ... -->
<Popup x:Name="popContainer"
IsOpen="{Binding IsPopupOpen,
RelativeSource={RelativeSource AncestorType={x:Type searchBox:KlasifikacijaBolestSearchBox}},
Mode=OneWay}">
解决方案。要实现列出的行为,您应使用IMultiValueConverter
和MultiBinding
。
public sealed class OrConverter : IMultiValueConverter
{
public object Convert(object[] values, System.Type targetType, object parameter, CultureInfo culture)
{
foreach (bool value in values)
{
if (value) { return true; }
}
return false;
}
public object[] ConvertBack(object value, System.Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
XAML:
<UserControl x:Class="Controls.KlasifikacijaBolestSearchBox.KlasifikacijaBolestSearchBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:controls="clr-namespace:Controls"
xmlns:converters="clr-namespace:Converters"
xmlns:itemClass="clr-namespace:Controls.KlasifikacijaBolestSearchBox.ViewModels"
x:Name="this"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" Loaded="this_Loaded">
<UserControl.Resources>
<converters:OrConverter x:Key="Converter" />
</UserControl.Resources>
<Grid x:Name="grid" DataContext="{Binding Class}">
<DockPanel LastChildFill="False">
<TextBox x:Name="txtSearch"
Background="WhiteSmoke"
DockPanel.Dock="Top" />
</DockPanel>
<Popup x:Name="popContainer"
Width="{Binding ElementName=txtSearch,
Path=ActualWidth}"
MinWidth="500"
MinHeight="500"
AllowsTransparency="True"
Placement="Bottom"
PlacementTarget="{Binding ElementName=txtSearch}"
PopupAnimation="Fade"
StaysOpen="True">
<Popup.IsOpen>
<MultiBinding Converter="{StaticResource OrConverter}">
<Binding ElementName="txtSearch" Path="IsMouseOver" Mode="OneWay" />
<Binding ElementName="txtSearch" Path="IsKeyboardFocusWithin" Mode="OneWay" />
<Binding ElementName="popContainer" Path="IsMouseOver" Mode="OneWay" />
</MultiBinding>
</Popup.IsOpen>
答案 1 :(得分:0)
尝试处理Popup的Opened和Closed事件。这是一个例子:Popup.Closed Event