c# - 带有添加的 MRU 项目的 WPF 组合框
问题描述
我的目标是创建一个组合框,它在打开时显示任何字符串列表(因此是标准行为),但是当用户选择其中一个字符串时,它会被添加到列表顶部的“最近使用”分隔符下。
本质上,我想要一个行为与在 MS Word 中选择字体完全相同的控件:
我的开始是创建一个带有附加依赖属性的自定义控件,该属性包含最近选择的项目。当用户从列表中选择一个项目时,此列表会更新。我不想修改原始项目列表,因为我的目标是获得一个可重用的控件,用户不必自己管理最新的项目。
private static readonly DependencyPropertyKey LastSelectedItemsPropertyKey =
DependencyProperty.RegisterReadOnly(
"LastSelectedItems",
typeof (Dictionary<string, int>),
typeof (MemoryCombobox),
new FrameworkPropertyMetadata(default(ObservableCollection<string>), FrameworkPropertyMetadataOptions.None));
public static readonly DependencyProperty LastSelectedItemsProperty = LastSelectedItemsPropertyKey.DependencyProperty;
我现在的问题是:如何在组合框的单个下拉列表中显示所有项目(标签和两个列表),如下所示:
---------------------
Label: Recently Selected
---------------------
<All items from the 'LastSelectedItems' DependencyProperty>
---------------------
Label: All Items
---------------------
<All items from the 'ItemsSource' property of the combobox
---------------------
我不想为此使用分组,因为这些项目不会在最近使用的项目下方的“所有项目”列表中重复,就像用户期望的那样。
解决方案
你有没有尝试过这些方面的东西。它使用分组,但以一种特殊的方式进行,因此不会从总列表/组中删除 mru-items:
XAML:
<ComboBox Name="MyCombo" SelectionChanged="MyCombo_SelectionChanged" VerticalAlignment="Top">
<ComboBox.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" Background="DarkGray" Foreground="White" FontWeight="Bold" />
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ComboBox.GroupStyle>
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" Margin="0,0,5,0" />
<TextBlock Text="{Binding Value}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
代码背后:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
m_preventFeedback = true;
ItemsList = new ObservableCollection<VMItem>
{
new VMItem(new Item("John", 1234), 2),
new VMItem(new Item("Peter", 2345), 2),
new VMItem(new Item("Michael", 3456), 2),
};
ListCollectionView view = new ListCollectionView(ItemsList);
view.GroupDescriptions.Add(new PropertyGroupDescription("CategoryId", new ItemGroupValueConverter()));
MyCombo.ItemsSource = view;
m_preventFeedback = false;
}
private ObservableCollection<VMItem> ItemsList = new ObservableCollection<VMItem>();
bool m_preventFeedback = false;
private void MyCombo_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (m_preventFeedback) return;
if (MyCombo.SelectedItem is VMItem item)
{
m_preventFeedback = true;
VMItem mru = ItemsList.FirstOrDefault(i => i.Name == item.Name && i.CategoryId == 1) ?? new VMItem(item.Item, 1);
ItemsList.Remove(mru);
ItemsList.Insert(0, mru);
MyCombo.SelectedItem = mru;
m_preventFeedback = false;
}
}
}
public class ItemGroupValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
switch ((int)value)
{
case 1: return "Last Used";
case 2: return "Available Items";
}
return "N/A";
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value;
}
}
public class VMItem : INotifyPropertyChanged
{
private Item m_item;
public VMItem(Item item, int categoryId)
{
m_item = item;
m_categoryId = categoryId;
}
public string Name
{
get { return m_item.Name; }
set
{
m_item.Name = value;
OnPropertyChanged("Name");
}
}
public int Value
{
get { return m_item.Value; }
set
{
m_item.Value = value;
OnPropertyChanged("Value");
}
}
private int m_categoryId;
public int CategoryId
{
get { return m_categoryId; }
set
{
m_categoryId = value;
OnPropertyChanged("CategoryId");
}
}
public Item Item => m_item;
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string property)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}
}
public class Item
{
public Item(string name, int value)
{
Name = name;
Value = value;
}
public string Name { get; set; }
public int Value { get; set; }
}
推荐阅读
- javascript - 在twilio php中断开呼叫后停止计时器
- spring-boot - 无法解析值“${spring.mail.host}”中的占位符“spring.mail.host”
- python - 如何在 Tensorflow 中以不同的学习率训练两个密集层?
- sql - 在时间序列中呈现累积平均值
- php - 从 API 获取 JSON 数据作为数组或对象
- python - Tensorflow 图的运行速度在每次迭代中不断下降
- javascript - 在没有 webpack 的情况下使用 Vue js 组件
- html - 如何更改 HTML 列表项的颜色(颜色:firebrick 不起作用
- elasticsearch - 从 Elasticsearch 5.6.x 升级到 6.4.0 后出现 index_out_of_bounds_exception 错误
- swift - 视图被合并而不是单独显示