我遇到了一个WPF Expander的问题,我在用户控件中有一个在ListBox中呈现的问题。基本上我正在尝试在ListBox中的每个ListItem上获取PopUpButton行为。当我打开Expander时,内容将在其他所有内容后面呈现,就像它是透明的一样,或者在z顺序中更低。我也尝试过使用WPF PopUp和Toggle Button(使用Karle Shivllet博客中描述的技术 - 使用弹出内容扩展控件)无济于事。
首先让我描述一下我正在尝试做什么。我有两个控件,显示我需要为我的应用程序配置的输入列表。为简单起见,一个用户控件用于配置图形的输入,另一个控件用于控制简单的Excel网格的输入。图形和网格的输入都具有需要在其上配置的属性。我开发了一个名为InputSelectControl的简单用户控件,它将呈现一个ListBox,其中包含要为图形或网格配置的输入列表。 ListBox中的每个ListItem包含输入名称的TextBlock(例如压力,ECG等)和WPF Expander,当clicke显示该输入的属性编辑器时。由于属性编辑器的显示方式会有所不同,具体取决于我是处理图形输入还是网格输入,我在InputSelectControl上使用了DependencyProperty,类型为ControlTemplate。这允许我的网格和图形各自提供编辑其输入属性所需的演示文稿。另请注意,我将不仅仅需要一个需要此行为的图形和网格,因此希望使其成为可以动态接收演示行为的用户控件。
我已经尝试将我的Expander放在我的属性编辑器模板中,曾尝试在各个地方尝试ZIndex,但总是以相同的行为结束,Expander弹出窗口显示在列表中的ListItems后面。
下面是一些代码,进一步描述了我的方法。希望有人可以帮助我摆脱这种泡沫。
表示我的Grid的XAML(可能是图形或其他东西)控制着我的InputSelectControl:
<UserControl x:Class="MyApp.GridView"
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:props="clr-namespace:PopupButtonDependencyProp" mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<!-- Specify the control tempalte we want loaded into the
properies popup for a grid-->
<ControlTemplate x:Key="GridPropertyEditorTemplate" TargetType="ContentControl">
<props:GridInputPropertyEditor />
</ControlTemplate>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Text="Hello Grid" Margin="5" />
<!-- Tell the InputSelectControl what template to load into Property
Window for each Grid Input item -->
<props:InputSelectControl Grid.Row="1"
DataContext="{Binding VmUsedInputs, Mode=OneWay}"
PropertyEditorTemplate="{StaticResource GridPropertyEditorTemplate}" />
</Grid>
</UserControl>
XAML代表我的 InputSelectControl ,它显示我的输入列表和每个ListItem的ContentControl占位符,我希望我的“弹出行为”用于编辑属性:
<UserControl x:Class="MyApp.InputSelectControl"
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:props="clr-namespace:PopupButtonDependencyProp"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<!-- Listbox holding our inputs. Assuming whatever we're contained in has
set our DataContext to a valid Input collection-->
<ListBox x:Name="inputsUsed" Grid.Row="1" ItemsSource="{Binding}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Auto"
SelectionMode="Multiple" ClipToBounds="True">
<ListBox.ItemTemplate>
<DataTemplate>
<Border x:Name="border" CornerRadius="7">
<StackPanel VerticalAlignment="Stretch" Orientation="Horizontal">
<!-- Input label-->
<TextBlock Text="{Binding Path=Label}" FontWeight ="Bold"
FontSize ="12" FontStyle = "Normal"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" Margin="5,0,5,0" />
<Expander x:Name="GridPropEditor" Header="Properties"
Height="Auto" Margin="5,0,0,0"
ToolTip="Open trace property dialog">
<!-- Properties button - The ContentControl below is rendering
the PropertyEditorTemplate that was set by whoever contains us -->
<ContentControl Template="{Binding PropertyEditorTemplate,
RelativeSource={RelativeSource AncestorType=props:InputSelectControl}}" />
</Expander>
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</UserControl>
C#表示我的DependencyProperty,用于注入弹出窗口中显示的属性编辑器模板。
/// <summary>
/// Interaction logic for InputSelectControl.xaml
/// </summary>
public partial class InputSelectControl : UserControl
{
#region Dependency Property stuff
/// <summary>
/// Dependency Property for control template to be rendered. This
/// lets us adorn the InputSelectControl with content in the Xaml.
/// The content can be different fore each instance of InputSelectControl.
/// </summary>
public static DependencyProperty PropertyEditorTemplateProperty =
DependencyProperty.Register("PropertyEditorTemplate",
typeof(ControlTemplate), typeof(InputSelectControl));
/// <summary>
/// PropertyEditorTemplate. This is how the property is set and get by WPF
/// </summary>
public ControlTemplate PropertyEditorTemplate
{
get { return GetValue(PropertyEditorTemplateProperty) as ControlTemplate; }
set { SetValue(PropertyEditorTemplateProperty, value); }
}
#endregion
/// <summary>
/// Constructor
/// </summary>
public InputSelectControl()
{
InitializeComponent();
}
}
XAML表示我的GridInputPropertyEditor,它是描述用于编辑网格属性的表示的模板。这对于图表来说会有所不同:
<UserControl x:Class="MyApp.GridInputPropertyEditor"
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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Canvas Panel.ZIndex=”99”>
<!-- Property Editor Control - Assumes DataContext holds to the properties
that need to be edited-->
<StackPanel Orientation="Vertical" Background="WhiteSmoke">
<!-- Lists the properties for a Grid to be edited. We could use
any layout we need here. -->
<ListBox ItemsSource="{Binding Properties}" Background="WhiteSmoke" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="5,5">
<TextBlock Text="{Binding Label}" FontWeight="Bold"/>
<TextBlock Text=":" />
<TextBox Text="{Binding Value}" Margin="10,0" Width="20" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</Canvas>
</UserControl>
使用Snoop我能够弄清楚如果我将ListBox项目的Z-Index设置为高数字,我的属性编辑器就会出现在前台。如果有人看到更好的方法让我知道。否则,我可以根据所选项目使用一些触发器来提升和降低zindex。
答案 0 :(得分:0)
好的,经过几次试验和磨难后,我能够使用代码来提出解决方案。我有兴趣找到一种方法来实现触发器,但我不确定这种方法是否可行。
这是更新扩展器XAML:
<Expander x:Name="GridPropEditor" Header="Properties" Height="Auto" Margin="5,0,0,0"
ToolTip="Open trace property dialog"
Tag="{Binding RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type ListBoxItem}}}"
PreviewMouseDown="GridPropEditor_PreviewMouseDown"
Expanded="GridPropEditor_Expanded">
这是我添加到我的xaml.cs文件背后的代码
//When an expander is expanded, collapse all the other expanders
private void GridPropEditor_Expanded(object sender, RoutedEventArgs e)
{
if (ExpandersSelected == null)
ExpandersSelected = new List<Expander>();
var expander = (sender as Expander);
var listbox = expander.Tag as ListBoxItem;
if (!ExpandersSelected.Contains(expander))
ExpandersSelected.Add(expander);
if (ExpandersSelected != null)
{
foreach(var x in ExpandersSelected)
{
if (x.Equals(expander))
{
listbox.SetValue(Panel.ZIndexProperty, 99);
continue;
}
var l = x.Tag as ListBoxItem;
x.IsExpanded = false;
l.SetValue(Panel.ZIndexProperty, 0);
}
}
}
解决方案背后的代码关闭了可能已经打开的所有扩展器,并通过将zindex设置为99将当前正在扩展的Expanders容器带到前台。
同样,如果有人有更好的解决方案,我会全力以赴。