我正在尝试创建一个包含World of warcraft项目列表的wpf组合框。我正在使用组合框的项目模板,以便项目图标和项目名称显示在组合框下拉列表中。它按原样工作,我可以开始输入项目名称,弹出窗口中的项目列表会自动过滤。
问题是当我点击一个项目时,我希望项目名称显示在组合框文本区域中。相反,我得到的是一个非常简短的ItemDisplayModel.ToString(),然后是一个空字符串。
ItemDisplayModel.ToString()是我从列表中选择的ItemDisplayModel类型。这有意义导致组合框控件ItemsSource属性包含ItemDisplayModel类型的数组。
但在我的AuctionHouseFilterItemNameModel.Value属性中,我检测到天气值已更改,如果是,则重建要在组合框中显示的项目列表。因为当我单击弹出列表中的项目时,组合框中的文本被更改为ItemDisplayModel.ToString(),它再次重建项目列表,这次没有匹配,因为ItemDisplayModel.ToString()与任何已知项目都不匹配名。
我想要做的就是当我单击弹出列表中的项目时,我希望将ItemDisplayModel.Name映射到AuctionHouseFilterItemNameModel.Value属性,并让组合框文本区域显示AuctionHouseFilterItemNameModel.Value。
这有意义吗?我尝试了很多不同的方式而且我很茫然。环顾网络也没有给我答案。我确信这个问题很容易解决,但解决办法使我无法解决。
这是我的XAML控件
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:AuctionHouseSearchFilters="clr-namespace:Codefarts.WowTracks.DataMinerWPF.Models.AuctionHouseSearchFilters"
xmlns:Models="clr-namespace:Codefarts.WowTracks.DataMinerAppCore.Models;assembly=Codefarts.WowTracks.DataMinerAppCore"
xmlns:DataMinerAppCore="clr-namespace:Codefarts.WowTracks.DataMinerAppCore;assembly=Codefarts.WowTracks.DataMinerAppCore"
xmlns:dataMinerWpf="clr-namespace:Codefarts.WowTracks.DataMinerWPF"
x:Name="userControl"
x:Class="Codefarts.WowTracks.DataMinerWPF.Controls.AuctionHouseSearchFilters.AuctionHouseItemNameControl"
mc:Ignorable="d"
d:DesignHeight="51" d:DesignWidth="283">
<UserControl.Resources>
<dataMinerWpf:UriToBitmapImageConverter x:Key="UriToImageConverter" />
<BitmapImage x:Key='defaultImage' UriSource='/Resources\118.png' />
<DataTemplate x:Key="ItemTemplate" DataType="Models:ItemDisplayModel" >
<StackPanel Orientation="Horizontal" Margin="0 5 0 5">
<Image Width="50" Height="50" Stretch="Fill" Source="{Binding IconUrl, Converter={StaticResource UriToImageConverter}, TargetNullValue={StaticResource defaultImage}}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<Label Content="{Binding Name}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</StackPanel>
</DataTemplate>
</UserControl.Resources>
<UserControl.DataContext>
<AuctionHouseSearchFilters:AuctionHouseFilterItemNameModel/>
</UserControl.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
</Grid.RowDefinitions>
<ComboBox x:Name="ItemList" MaxDropDownHeight="592" Grid.Row="0" ItemsSource="{Binding ItemDisplayModels}" ItemTemplate="{StaticResource ItemTemplate}" IsEditable="True" IsTextSearchEnabled="True" IsTextSearchCaseSensitive="False" Text="{Binding Value}" >
</ComboBox>
</Grid>
</UserControl>
这是我背后的代码
public partial class AuctionHouseItemNameControl : UserControl, IAuctionHouseFilterControl
{
private Application app;
public AuctionHouseItemNameControl()
{
InitializeComponent();
}
public void SetModel(IAuctionHouseSearchFilter model)
{
this.DataContext = model;
}
public void SetApplication(Application app)
{
this.app = app;
}
private void ItemList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
//if (model.Handled)
//{
// return;
//}
// model.Handled = true;
if (e.AddedItems != null && e.AddedItems.Count > 0)
{
var model = this.DataContext as Models.AuctionHouseSearchFilters.AuctionHouseFilterItemNameModel;
var item = e.AddedItems[0] as ItemDisplayModel;
// this.ItemList.SelectedValue = item.Name;
model.Value = item.Name;
// this.ItemList.SelectedItem = item.Name;
}
// model.Handled = false;
}
}
这是我的数据模型
[Export(typeof(IAuctionHouseSearchFilter))]
public class AuctionHouseFilterItemNameModel : IAuctionHouseSearchFilter, INotifyPropertyChanged
{
private string value;
private bool connected;
private Application app;
private ItemDisplayModel[] displayItems;
private CancellationTokenSource backgroundCancel;
private bool buildingDisplayItems;
private readonly object lockObject = new object();
private ItemDisplayModel displayValue;
// private bool Handled { get; set; }
public ItemDisplayModel DisplayValue
{
get
{
return this.displayValue;
}
set
{
if (value == null)
{
return;
}
this.Value = value.Name;
this.displayValue = value;
this.OnPropertyChanged();
}
}
public string Value
{
get
{
return this.value;
}
set
{
//if (this.Handled)
//{
// return;
//}
if (value == this.value)
{
return;
}
this.value = value;
// this.Handled = true;
this.OnPropertyChanged();
var cancellationTokenSource = this.backgroundCancel;
if (cancellationTokenSource != null)
{
cancellationTokenSource.Cancel();
}
this.BuildDisplayItems();
// this.Handled = false;
}
}
public IEnumerable<AuctionDataModel> Filter(MainFilterModel model, IEnumerable<AuctionDataModel> items)
{
if (!this.connected)
{
return items;
}
// get item id from it's name
var list = this.app.ItemNames[model.SelectedRegion];
var id = list.FirstOrDefault(x => x.Name.ToLowerInvariant().Contains(this.value.Trim().ToLowerInvariant()));
return items.Where(x => id != null && x.ItemId == id.Id);
}
public IEnumerable<ItemDisplayModel> ItemDisplayModels
{
get
{
return this.displayItems;
}
}
public async void BuildDisplayItems()
{
if (this.buildingDisplayItems)
{
return;
}
if (!this.connected)
{
this.displayItems = null;
}
// return this.GetDisplayItems();
this.buildingDisplayItems = true;
this.backgroundCancel = new CancellationTokenSource();
this.OnPropertyChanged("ItemDisplayModels");
await Task.Factory.StartNew(
() =>
{
var originalItems = this.displayItems;
this.displayItems = new[] { new ItemDisplayModel() { Name = "Rebuilding list..." } };
var correctedSearchValue = this.value.Trim().ToLowerInvariant();
//lock (this.lockObject)
//{
this.displayItems = (string.IsNullOrWhiteSpace(this.value) ?
this.app.DisplayItemModels :
this.app.DisplayItemModels.Where(x => x.Name.ToLowerInvariant().Contains(correctedSearchValue))).Take(100).AsParallel().ToArray();
this.buildingDisplayItems = false;
this.OnPropertyChanged("ItemDisplayModels");
},
this.backgroundCancel.Token);
}
public string Name
{
get
{
return "Item Name";
}
}
public Type Control
{
get
{
return typeof(AuctionHouseItemNameControl);
}
}
public virtual IAuctionHouseSearchFilter Clone()
{
return new AuctionHouseFilterItemNameModel()
{
Value = this.Value
};
}
public void Connect(Application app)
{
if (this.connected)
{
return;
}
this.app = app;
this.connected = true;
}
public void Disconnect()
{
if (!this.connected)
{
return;
}
this.app = null;
this.connected = false;
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = this.PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
public class ItemDisplayModel : INotifyPropertyChanged
{
private string iconUrl;
private string region;
private string name;
private int itemId;
public int ItemId
{
get
{
return this.itemId;
}
set
{
if (value == this.itemId)
{
return;
}
this.itemId = value;
this.OnPropertyChanged();
}
}
public string Name
{
get
{
return this.name;
}
set
{
if (value == this.name)
{
return;
}
this.name = value;
this.OnPropertyChanged();
}
}
public string Region
{
get
{
return this.region;
}
set
{
if (value == this.region)
{
return;
}
this.region = value;
this.OnPropertyChanged();
}
}
public string IconUrl
{
get
{
return this.iconUrl;
}
set
{
if (value == this.iconUrl)
{
return;
}
this.iconUrl = value;
this.OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = this.PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
答案 0 :(得分:1)
问题是当我点击一个项目时,我希望项目名称显示在组合框文本区域中。相反,我得到的是一个非常简短的ItemDisplayModel.ToString(),然后是一个空字符串。
要在Name
使用TextSearch.TextPath的可编辑文本区域中显示ComboBox
属性,以便ComboBox
定义如下:
<ComboBox x:Name="ItemList"
Grid.Row="0"
IsEditable="True"
IsTextSearchCaseSensitive="False"
IsTextSearchEnabled="True"
ItemTemplate="{StaticResource ItemTemplate}"
ItemsSource="{Binding ItemDisplayModels}"
MaxDropDownHeight="592"
TextSearch.TextPath="Name" />
现在,当从下拉列表中选择某个项目而不是看到ItemDisplayModel.ToString()
时,您会看到Name
属性。