[英]MaterialDesignInXaml ComboBox - Clear button issue
我正在使用 MaterialDesignInXaml 和 ReactiveUI 構建 WPF 應用程序。 我有以下 XAML 代碼:
<ItemsControl ItemsSource="{Binding Filters}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type local:FilterViewModel}">
<ComboBox
Margin="6,0,6,12"
materialDesign:HintAssist.HelperText="{Binding Name}"
materialDesign:HintAssist.Hint="{Binding Name}"
materialDesign:TextFieldAssist.HasClearButton="True" /// <--- clear button doesn't work!
ItemsSource="{Binding Options}"
SelectedItem="{Binding SelectedOption}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
以及對應的 ViewModel:
public class MainWindowViewModel : ReactiveObject
{
public List<FilterViewModel> Filters { get; set; } = new();
public MainWindowViewModel()
{
Filters = Enumerable.Range(1, 3).Select(x => new FilterViewModel()
{
Name = $"Filter {x}",
Options = new ObservableCollection<string>(Enumerable.Range(1, 5).Select(y => y.ToString()))
}).ToList();
}
}
public class FilterViewModel : ReactiveObject
{
public ObservableCollection<string> Options { get; set; } = new();
public string Name
{
get => _name;
set => this.RaiseAndSetIfChanged(ref _name, value);
}
public string SelectedOption
{
get => _selectedOption;
set => this.RaiseAndSetIfChanged(ref _selectedOption, value);
}
private string _selectedOption;
private string _name;
}
這給了我很好的三個組合框:
問題是ComboBox
清除按鈕在單擊時無效。 它根本不做任何事情,沒有錯誤,什么都沒有。 我在這里錯過了什么嗎? 為什么它不起作用?
這是在 GitHub 上跟蹤的 MaterialDesign 中的一個錯誤:
問題出在ClearText.OnClearCommand
方法中,該方法是為綁定到清除按鈕的ClearCommand
執行的。 假設事件的Source
是ComboBox
,但它是按鈕本身,因此該方法不會清除任何內容。
不幸的是, ClearCommand
在控制模板中是硬連線的,請參見此處:
<Button
x:Name="PART_ClearButton"
Grid.Column="2"
Height="Auto"
Padding="2,0,0,0"
Command="{x:Static internal:ClearText.ClearCommand}"
Focusable="False"
Style="{StaticResource MaterialDesignToolButton}">
因此,清除命令的修復需要復制ClearText
類、修復錯誤、復制ComboBox
的所有相關樣式並在控件模板中使用命令的本地修復版本。
獎勵回合:您可以在代碼中解決這個問題,但這或多或少是一個骯臟的修復。 您可以在加載ComboBox
時搜索清除按鈕並重新分配命令的固定版本。
我使用Microsoft.Xaml.Behaviors.Wpf NuGet 包將此修復封裝到一個可重用的組件中,該組件可以輕松集成,但您也可以改用代碼隱藏。
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
using MaterialDesignThemes.Wpf.Internal;
using Microsoft.Xaml.Behaviors;
namespace SignumsAwesomeApp
{
public class MaterialDesignComboBoxClearButtonFixBehavior: Behavior<ComboBox>
{
private static readonly RoutedCommand ClearCommand = new RoutedCommand();
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.Loaded += OnLoaded;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.Loaded -= OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
if (!ClearText.GetHandlesClearCommand(AssociatedObject))
return;
AssociatedObject.CommandBindings.Add(new CommandBinding(ClearCommand, OnClearCommand));
FindChild<Button>(AssociatedObject, "PART_ClearButton").Command = ClearCommand;
}
private void OnClearCommand(object sender, ExecutedRoutedEventArgs e)
{
AssociatedObject.SetCurrentValue(ComboBox.TextProperty, null);
AssociatedObject.SetCurrentValue(Selector.SelectedItemProperty, null);
}
private static T FindChild<T>(DependencyObject parent, string childName)
where T : DependencyObject
{
if (parent == null)
return null;
T foundChild = null;
var childrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (var i = 0; i < childrenCount; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
if (!(child is T childType))
{
foundChild = FindChild<T>(child, childName);
if (foundChild != null) break;
}
else if (!string.IsNullOrEmpty(childName))
{
if (childType is FrameworkElement frameworkElement && frameworkElement.Name == childName)
{
foundChild = childType;
break;
}
}
else
{
foundChild = childType;
break;
}
}
return foundChild;
}
}
}
FindChild
方法來自@CrimsonX對這個問題的回答:
您必須將行為添加到 XAML 中的ComboBox
中,如下所示:
<ComboBox ...>
<b:Interaction.Behaviors>
<local:MaterialDesignComboBoxClearButtonFixBehavior/>
</b:Interaction.Behaviors>
</ComboBox>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.