【问题标题】:How to dock listbox to a textbox overlapping other items如何将列表框停靠到与其他项目重叠的文本框
【发布时间】:2020-06-27 05:41:13
【问题描述】:

我正在尝试使用自动完成下拉列表框制作文本框。

问题在于列表框没有空间,因为文本框下方还有其他项目。虽然,在屏幕截图上看不到,文本框和按钮之间的空间将被表格填充。

有没有办法将列表框停靠或对齐到给定文本框的底部,而不考虑布局中的其他项目?

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="70"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="70"/>
    </Grid.RowDefinitions>
    <TextBox Grid.Row="0" x:Name="txtb_name"></TextBox>


    <Grid Grid.Row="2" VerticalAlignment="Bottom">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Button Grid.Column="0" x:Name="btn_givecancel" Content="Cancel" Height="70" FontSize="18.667" Click="btn_givecancel_Click"/>
        <Button Grid.Column="1" x:Name="btn_giveaccept" Content="Accept" Height="70" FontSize="18.667" Click="btn_giveaccept_Click"/>
    </Grid>
</Grid>

【问题讨论】:

  • 2 条建议。首先,如果可用,请使用预构建的控件。其次,要么使用 Popup 窗口,要么使用 RowSpan/ColSpan 来绘制其他控件。
  • 我不明白重叠的独立列表框和文本框下拉列表之间的区别。自动完成有一些选项你可以看看。
  • @Qeeet:你希望/期望ListBox 有什么高度?

标签: c# wpf xaml layout


【解决方案1】:

这是我的实现:

有一个转换器,可以获取可能的自动建议项目总数和当前查看次数:

<local:IntToVisibilityConverter x:Key="IntToVisibilityConverter"/>

然后是带有 TextBox、ListBox 和 Button 控件的表单。

<Grid Margin="50">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <TextBox Grid.Row="0" Text="{Binding UserText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" DockPanel.Dock="Top"/>
        <ListBox Grid.Row="1" Grid.RowSpan="2" VerticalAlignment="Top" MaxHeight="55" ItemsSource="{Binding SuggestionsFiltered, UpdateSourceTrigger=PropertyChanged}"
                 Canvas.ZIndex="1">
            <ListBox.Visibility>
                <MultiBinding Converter="{StaticResource IntToVisibilityConverter}">
                    <Binding Path="MaxCount"/>
                    <Binding Path="SuggestionsFiltered.Count"/>
                </MultiBinding>
            </ListBox.Visibility>
        </ListBox>

        <StackPanel Grid.Row="2" Orientation="Horizontal" Margin="0 50 0 0">
            <Button Height="20" Width="100">Clear</Button>
            <Button Height="20" Width="100" Margin="10 0 0 0">Accept</Button>
        </StackPanel>

    </Grid>

最后,这是我的 DataContext:

public class TheDataContext
    {
        public TheDataContext()
        {
            FillData();

            _SuggestionsFiltered = CollectionViewSource.GetDefaultView(_SuggestionSource);
            _SuggestionsFiltered.Filter = obj =>
            {
                var opt = obj as string;
                if (string.IsNullOrEmpty(_UserText) || _UserText.Length == 0)
                    return true;

                return string.Join("", opt.Take(_UserText.Length)) == _UserText;
            };
        }

        private void FillData()
        {
            _SuggestionSource = new List<string>();
            _SuggestionSource.Add("Alpha");
            _SuggestionSource.Add("Alpines");
            _SuggestionSource.Add("Bravo");
            _SuggestionSource.Add("Brood");
            _SuggestionSource.Add("Charlie");
            _SuggestionSource.Add("Charles");
            _SuggestionSource.Add("Charlotte");
        }

        private string _UserText;

        public string UserText
        {
            get => _UserText;
            set
            {
                _UserText = value;
                _SuggestionsFiltered.Refresh();
            }
        }

        private List<string> _SuggestionSource;

        public int MaxCount => _SuggestionSource.Count;

        private ICollectionView _SuggestionsFiltered;

        public ICollectionView SuggestionsFiltered
        {
            get => _SuggestionsFiltered;
        }
    }

注意 ICollectionView 周围的所有代码。另外,我在 xaml 中强制设置了一些边距,以显示 Listbox 被绘制在其他控件上的情况(由 ZIndex 提供)。

如果您使用此代码,请记住处理 ListBox 上的选定事件,然后将 textBox Text 设置为该值。同时隐藏列表框。那里有点杂耍。

最后,如果您有兴趣,这里是转换器:

public class IntToVisibilityConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            int maxCount = System.Convert.ToInt32(values[0]);
            int count = System.Convert.ToInt32(values[1]);

            if (count > 0 && count != maxCount)
                return Visibility.Visible;
            return Visibility.Collapsed;
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-27
    • 2020-09-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多