如何将用户控件放在所有其他控件之上的静态层中?
Posted
技术标签:
【中文标题】如何将用户控件放在所有其他控件之上的静态层中?【英文标题】:How to put a user control in a static layer ontop of all other controls? 【发布时间】:2015-11-10 23:02:41 【问题描述】:我正在使用 XAML 和 C# 为 WPF 开发一个自动完成用户控件。
我想让建议弹出窗口出现在所有控件之上。目前我的弹出窗口是 ListView
。这会导致问题,因为每当我决定显示它时,UI 都必须为其找到一个位置,并且这样做会将其下方的所有控件进一步向下移动。
我怎样才能避免这种情况?我想我必须把它放在一个高于所有其他控件的层中?
【问题讨论】:
为什么不把它放在自己的窗口中呢? 自动建议框的窗口?不是一个好主意。 那么这是代码完成类型的控件吗? 不,它是一个控件,您可以为它提供一个它可以建议的项目数据集,并且它可以与它们一起使用。 【参考方案1】:我之前使用 WPF Popup 控件结合文本框编写了“自动完成”样式控件。如果您使用 Popup,它应该像您所说的那样出现在其他所有内容之上的图层中。只需使用 Placement of Bottom 将其与文本框的底部对齐。
这是我不久前写的一个例子。基本上它是一个文本框,当您键入时会弹出一个建议弹出窗口,并且当您键入更多时,它会细化选项。如果您愿意,您可以很容易地更改它以支持多字自动完成样式代码编辑情况:
XAML:
<Grid>
<TextBox x:Name="textBox"
Text="Binding Text, Mode=TwoWay, RelativeSource=RelativeSource Mode=FindAncestor, AncestorType=x:Type local:IntelliSenseUserControl"
KeyUp="textBox_KeyUp"/>
<Popup x:Name="popup"
Placement="Bottom"
PlacementTarget="Binding ElementName=textBox"
IsOpen="False"
Width="200"
Height="300">
<ListView x:Name="listView"
ItemsSource="Binding FilteredItemsSource, RelativeSource=RelativeSource Mode=FindAncestor, AncestorType=x:Type local:IntelliSenseUserControl"
SelectionChanged="ListView_Selected"/>
</Popup>
</Grid>
代码隐藏:
public partial class IntelliSenseUserControl : UserControl, INotifyPropertyChanged
public IntelliSenseUserControl()
InitializeComponent();
DependencyPropertyDescriptor prop = DependencyPropertyDescriptor.FromProperty(ItemsSourceProperty, typeof(IntelliSenseUserControl));
prop.AddValueChanged(this, ItemsSourceChanged);
private void ItemsSourceChanged(object sender, EventArgs e)
FilteredItemsSource = new ListCollectionView((IList)ItemsSource);
FilteredItemsSource.Filter = (arg) => return arg == null || string.IsNullOrEmpty(textBox.Text) || arg.ToString().Contains(textBox.Text.Trim()); ;
public string Text
get return (string)GetValue(TextProperty);
set SetValue(TextProperty, value);
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(IntelliSenseUserControl), new FrameworkPropertyMetadata(null) BindsTwoWayByDefault = true );
public object ItemsSource
get return (object)GetValue(ItemsSourceProperty);
set SetValue(ItemsSourceProperty, value);
public static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.Register("ItemsSource", typeof(object), typeof(IntelliSenseUserControl), new PropertyMetadata(null));
#region Notified Property - FilteredItemsSource (ListCollectionView)
public ListCollectionView FilteredItemsSource
get return filteredItemsSource;
set filteredItemsSource = value; RaisePropertyChanged("FilteredItemsSource");
private ListCollectionView filteredItemsSource;
#endregion
private void textBox_KeyUp(object sender, KeyEventArgs e)
if (e.Key == Key.Return || e.Key == Key.Enter)
popup.IsOpen = false;
else
popup.IsOpen = true;
FilteredItemsSource.Refresh();
private void UserControl_LostFocus(object sender, RoutedEventArgs e)
popup.IsOpen = false;
private void ListView_Selected(object sender, RoutedEventArgs e)
if (listView.SelectedItem != null)
Text = listView.SelectedItem.ToString().Trim();
public event PropertyChangedEventHandler PropertyChanged;
void RaisePropertyChanged(string name)
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(name));
【讨论】:
【参考方案2】:如果您的 Window 的内容容器是一个 Grid,您可以简单地执行类似的操作
<ListBox Grid.RowSpawn="99" Grid.ColumnSpan="99"/>
“模拟”一个绝对位置。然后,您只需使用Margin, HorizontalAlignment and VerticalAlignment
设置其位置,使其位于所需控件周围。
【讨论】:
以上是关于如何将用户控件放在所有其他控件之上的静态层中?的主要内容,如果未能解决你的问题,请参考以下文章
Compact Framework/Threading - 选择选项后,MessageBox 显示在其他控件之上
Delphi 2007 - ManualFloat 导致小部件控件浮动在所有其他窗口之上