如何在下拉菜单中加载组合框项目
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在下拉菜单中加载组合框项目相关的知识,希望对你有一定的参考价值。
我需要使用带有一些工作表的excel工作簿。要将可用的工作表加载到组合框中,我需要打开工作簿并遍历所有工作表,然后将它们添加到组合框中。这花费了大量时间,用户需要等待。如果用户不想更改预加载的属性,则此时间很短。因此,我只想在需要时填写列表项,但显示预选属性,该属性是在应用启动时从设置文件加载的。
那么有没有办法在下拉菜单中加载项目?或者更好的是,如何绑定下拉菜单中触发的命令来加载项目?
<ComboBox SelectedItem="{Binding Worksheet}" ItemsSource="{Binding WorkSheets}" x:Name="cbWorkSheet" Padding="4">
...哦,我知道如何将命令绑定到按钮,所以我需要组合框的特殊提示,而不是一般的命令:)
UPDATE我解决了触发“加载”的问题,并且列表已填充,但是我需要显示最后一个选定的值(在启动时作为绑定属性工作表加载)
<ComboBox
x:Name="cbWorkSheet"
SelectedItem="{Binding Worksheet}"
ItemsSource="{Binding WorkSheets}"
IsEditable="True"
Padding="4">
<i:Interaction.Triggers>
<i:EventTrigger EventName="DropDownOpened" SourceObject="{Binding ElementName=cbWorkSheet}">
<i:InvokeCommandAction Command="{Binding LoadBACnetWsCombobox}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
有了该绑定,组合框保持为空,直到我将其下拉:(
原始答案:不正确,发布日期2020/06/02:
如果您需要在打开下拉菜单之前填充SelectedItem,则可能应该将EventTrigger的EventName从DropDownOpened
更改为Loaded
。
那样,在向用户显示组合框之前,将运行LoadBACnetWsComboBox
,希望可以设置您的Worksheet
。然后,组合框将显示给用户。
修改后的答案,发布日期2020/06/03:
根据您对我的原始答案的评论,我已经使用我的这份工作副本进行了修改。我选择删除触发器和命令操作(我没有Interaction命名空间),而是采用了ComboBox的IsDropDownOpen属性之外的方式使用MVVM模式。
MainWindow.xaml:
<Window x:Class="ComboBoxDropdownTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ComboBoxDropdownTest"
mc:Ignorable="d"
Title="{Binding Title}" Height="450" Width="800">
<Window.Resources>
<DataTemplate DataType="{x:Type local:WorksheetViewModel}">
<Grid>
<TextBlock Text="{Binding Name,FallbackValue=FixYourBinding}" />
</Grid>
</DataTemplate>
</Window.Resources>
<Grid>
<ComboBox x:Name="cbWorkSheet"
SelectedItem="{Binding Worksheet, Mode=OneWay}"
ItemsSource="{Binding Worksheets}"
IsEditable="True"
Padding="4"
IsDropDownOpen="{Binding IsDropDownOpen}"
VerticalAlignment="Center"
Margin="5"
Width="400"
Text="{Binding SelectedAtStartup}"
>
<ComboBox.ItemContainerStyle>
<Style TargetType="ComboBoxItem">
<Setter Property="IsSelected" Value="{Binding Selected}"/>
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>
</Grid>
</Window>
MainWindow.xaml.cs:
using System.Windows;
namespace ComboBoxDropdownTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindowViewModel ViewModel
{
get { return this.DataContext as MainWindowViewModel; }
}
public MainWindow()
{
InitializeComponent();
var vm = new MainWindowViewModel();
this.DataContext = vm;
this.Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
this.ViewModel.Initialize();
}
}
}
MainWindowViewModel.cs:
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Threading.Tasks;
namespace ComboBoxDropdownTest
{
public class MainWindowViewModel : ViewModelBase
{
private string selectedAtStartup;
private bool isDropDownOpen;
private ObservableCollection<WorksheetViewModel> worksheets;
private bool loadedOnce;
public MainWindowViewModel()
{
this.PropertyChanged += OnViewModelPropertyChanged;
}
public string Title { get => "This is a combobox dropdown test"; }
public string SelectedAtStartup { get => this.selectedAtStartup; set { this.selectedAtStartup = value; OnPropertyChanged(); } }
public bool IsDropDownOpen { get => this.isDropDownOpen; set { this.isDropDownOpen = value; OnPropertyChanged(); } }
public WorksheetViewModel Worksheet
{
get { return this.Worksheets.FirstOrDefault(o => o.Selected); }
}
public ObservableCollection<WorksheetViewModel> Worksheets
{
get
{
if (this.worksheets == null)
{
this.worksheets = new ObservableCollection<WorksheetViewModel>();
}
return this.worksheets;
}
}
public void Initialize()
{
// Simulates the loading of your selected property at startup
this.SelectedAtStartup = "Worksheet3";
}
private async Task LoadBACnetWsCombobox()
{
for (int i = 0; i < 10; i++)
{
var worksheet = new Worksheet() { Name = $"Worksheet{i}" };
this.Worksheets.Add(new WorksheetViewModel(worksheet));
}
// simulate a long 2-second delay load time
await Task.Delay(2000);
}
private async void OnViewModelPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(this.IsDropDownOpen) && this.IsDropDownOpen)
{
// Do your Command action here
if (!loadedOnce)
{
this.loadedOnce = true;
await this.LoadBACnetWsCombobox();
}
}
}
}
}
WorksheetViewModel.cs:
namespace ComboBoxDropdownTest
{
public class WorksheetViewModel : ViewModelBase<Worksheet>
{
public WorksheetViewModel(Worksheet model) : base(model)
{
}
public string Name { get => this.Model.Name; set { this.Model.Name = value; OnPropertyChanged(); } }
public override string ToString()
{
return this.Name;
}
}
}
ViewModelBase.cs:
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace ComboBoxDropdownTest
{
public class ViewModelBase : INotifyPropertyChanged
{
private bool selected;
public event PropertyChangedEventHandler PropertyChanged;
public bool Selected { get => this.selected; set { this.selected = value; OnPropertyChanged(); } }
public void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class ViewModelBase<T> : ViewModelBase
{
public T Model { get; private set; }
public ViewModelBase(T model) : base()
{
this.Model = model;
}
}
}
Worksheet.cs:
namespace ComboBoxDropdownTest
{
public class Worksheet
{
public string Name { get; set; }
}
}
以上是关于如何在下拉菜单中加载组合框项目的主要内容,如果未能解决你的问题,请参考以下文章
如何同步组合框和文本字段值。即如何从存储在文本字段中加载不同的值,而我正在更改组合框上的值
如何在 AdminLte 多选下拉列表中加载项目以进行更新 - Laravel 8