【问题标题】: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 都必须为其找到一个位置,并且这样做会将其下方的所有控件进一步向下移动。

我怎样才能避免这种情况?我想我必须把它放在一个高于所有其他控件的层中?

【问题讨论】:

  • 为什么不把它放在自己的窗口中呢?
  • 自动建议框的窗口?不是一个好主意。
  • 那么这是代码完成类型的控件吗?
  • 不,它是一个控件,您可以为它提供一个它可以建议的项目数据集,并且它可以与它们一起使用。

标签: c# wpf xaml


【解决方案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 设置其位置,使其位于所需控件周围。

    【讨论】:

      猜你喜欢
      • 2011-04-26
      • 1970-01-01
      • 1970-01-01
      • 2010-12-25
      • 2011-02-21
      • 2012-06-02
      • 2011-07-23
      • 2017-03-13
      • 2012-08-06
      相关资源
      最近更新 更多