gpt4 book ai didi

wpf - 在 ComboBox 的 ItemsPanel 上方添加其他控件

转载 作者:行者123 更新时间:2023-12-04 15:57:57 25 4
gpt4 key购买 nike

我想做一个可搜索的ComboBox ,搜索框为 TextBox出现在 ItemsPanel 上方当ComboBox下拉菜单展开。我想我需要制作一个自定义控件来实现搜索功能,但首先我只是想获得 TextBox使用普通 ComboBox 显示.这是我当前的尝试,当我尝试展开下拉列表时会产生异常:

<Style x:Key="FilteredComboBox" TargetType="ComboBox">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel>
<TextBox/>
<StackPanel IsItemsHost="True"
Orientation="Horizontal"
VerticalAlignment="Center"
HorizontalAlignment="Center"/>
</StackPanel>

</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>

这产生的异常是:

Cannot explicitly modify Children collection of Panel used as ItemsPanel for ItemsControl. ItemsControl generates child elements for Panel.



我很确定有办法让它做我想做的事,但经过几个小时的谷歌搜索和反复试验,我现在头晕目眩。任何帮助将不胜感激!

最佳答案

虽然我对此的回答都是正确的,但我认为他们中的任何一个都没有真正回答我的问题,足以被标记为解决方案。我最终做的是从 ComboBox 派生一个自定义控件(右键单击设计器中的 ComboBox 并选择 Edit Template -> Edit a Copy,这会为我复制的 ComboBox 模板生成一大堆 XAML 代码到我制作的自定义控件项目的 Generic.xaml 文件)。然后我编辑了生成的 XAML 代码的 Popup 部分,在 ItemsPresenter 上方添加了一个 WatermarkTextBox(来自扩展的 WPF 工具包),如下所示:

<Popup x:Name="PART_Popup" AllowsTransparency="true" Grid.ColumnSpan="2" IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}" Margin="1" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Placement="Bottom">
<Themes:SystemDropShadowChrome x:Name="Shdw" Color="Transparent" MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{Binding ActualWidth, ElementName=MainGrid}">
<Border x:Name="DropDownBorder" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}">
<ScrollViewer x:Name="DropDownScrollViewer">
<Grid RenderOptions.ClearTypeHint="Enabled">
<Canvas HorizontalAlignment="Left" Height="0" VerticalAlignment="Top" Width="0">
<Rectangle x:Name="OpaqueRect" Fill="{Binding Background, ElementName=DropDownBorder}" Height="{Binding ActualHeight, ElementName=DropDownBorder}" Width="{Binding ActualWidth, ElementName=DropDownBorder}"/>
</Canvas>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<xtk:WatermarkTextBox Grid.Row="0"
Visibility="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource booleanToVisibilityConverter}}"
Watermark="Type here to filter..."
Text="{Binding SearchFilter, RelativeSource={RelativeSource TemplatedParent}, UpdateSourceTrigger=PropertyChanged}">
</xtk:WatermarkTextBox>
<ItemsPresenter x:Name="ItemsPresenter" Grid.Row="1" KeyboardNavigation.DirectionalNavigation="Contained" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Grid>
</Grid>
</ScrollViewer>
</Border>
</Themes:SystemDropShadowChrome>
</Popup>

我将 Text 绑定(bind)到的 SearchFilter 属性是我的自定义控件代码隐藏中的一个属性,然后它执行 ComboBox 中值的实际过滤。这有点超出了我原来的问题的范围,但如果有人好奇,这就是我如何进行过滤:
public class SearchableComboBox : ComboBox
{
public const string SearchFilterPropertyName = "SearchFilter";
public readonly static DependencyProperty SearchFilterProperty;
public string SearchFilter
{
get { return (string)GetValue(SearchFilterProperty); }
set { SetValue(SearchFilterProperty, value); }
}

static SearchableComboBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(SearchableComboBox), new FrameworkPropertyMetadata(typeof(SearchableComboBox)));

SearchFilterProperty = DependencyProperty.Register(SearchFilterPropertyName, typeof(string), typeof(SearchableComboBox),
new PropertyMetadata(string.Empty, new PropertyChangedCallback(SearchFilter_PropertyChanged)));

}

private static void SearchFilter_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((SearchableComboBox)d).RefreshFilter();
}

private void RefreshFilter()
{
if (this.ItemsSource != null)
{
ICollectionView view = CollectionViewSource.GetDefaultView(this.ItemsSource);
view.Refresh();
}
}

private bool FilterPredicate(object value)
{
if (value == null)
return false;

if (string.IsNullOrEmpty(SearchFilter))
return true;

return value.ToString().Contains(SearchFilter, StringComparison.CurrentCultureIgnoreCase);
}

protected override void OnItemsSourceChanged(IEnumerable oldValue, IEnumerable newValue)
{
if (newValue != null)
{
ICollectionView view = CollectionViewSource.GetDefaultView(newValue);
view.Filter += this.FilterPredicate;
}

if (oldValue != null)
{
ICollectionView view = CollectionViewSource.GetDefaultView(oldValue);
view.Filter -= this.FilterPredicate;
}

base.OnItemsSourceChanged(oldValue, newValue);
}

关于wpf - 在 ComboBox 的 ItemsPanel 上方添加其他控件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15096507/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com