这是我要做的事情的要点。
Heres'我的英雄课:
namespace TomeOfNewerth_WPF_
{
public enum HeroType
{
Agility,
Strength,
Intelligence
}
public enum AttackType
{
Melee,
Ranged,
}
class Hero
{
public string Faction;
public string Name;
public HeroType HeroType;
public string Backstory;
public double MinimumDamage;
public double MaximumDamage;
public double Armor;
public double MoveSpeed;
public AttackType AttackType;
public double AttackRange;
public double AttackRate;
public int Strength;
public int Agility;
public int Intelligence;
public string DOTAVersion;
//Default constructer required for XML serialization.
public Hero()
{ }
/// <summary>
/// This method returns a hero full of the necessary information.
/// </summary>
/// <param name="Name">Name of the hero.</param>
/// <returns>Returns an instace of the Hero class chock full of information.</returns>
public Hero GetHero(string Name)
{
Hero NewHero = new Hero();
NewHero.Faction = "Legion";
NewHero.Name = "Andromeda";
//Yada yada yada. I have to complete this, so disregard it.
return NewHero;
}
}
}
该类的每个属性都是XML元素。我已将所有信息手动制表成XML文件,以便将其反序列化为Hero类,并将实例转发到需要的地方。
有一个用例我无法理解。
我有两个按钮,ViewGood和ViewEvil。
Hero类中有一个名为Faction的属性,我必须过滤掉哪些英雄有好,哪些英雄有邪恶。
我在想做什么:
我有一个循环的方法 通过XML和中的每个节点 返回包含所有的List 英雄姓名与要求的HEROTYPE相匹配。
使用该列表,我可以 做一个foreach和所有英雄 在窗体上有一个Image控件 使用x:名称设置为英雄 名字,我可以做.Visibilty = Visibility.False给所有人,并设置它 忠实于每个英雄的名字 名单。有效隐藏每个Image控件 这不在名单上。
我向你们提问的是,我做的事情是完全迟钝的吗?我真的想花更多的时间让这个程序有很好的干净代码,因为我想学习比什么都重要。
正如我父亲所说,“坏习惯很容易学习,强奸你的好习惯。”
非常感谢。 :)
答案 0 :(得分:4)
我不明白。您想要一个按属性过滤的列表吗?
喜欢这个吗?
List<Hero> heroes = GetYourHeroes();
var goodGuys = heroes.Where(hero => hero.Faction == "Jedi");
编辑以回答评论:
你的第二行是否相当于做一个foreach并询问是否hero.Faction ==“Jedi”
或多或少,是的。在大多数情况下,它的行为相同,但底层LINQ的行为完全不同。如果您喜欢这种语法,我建议您阅读本文或查看本网站上的LINQ问题。
可以咬你的主要差异是默认情况下这是懒惰的。
Where(hero => hero.Faction == "Jedi")
会返回IEnumerable<Hero>
并且实际上不会按照您的要求执行操作,除非您真正手动或通过将结果转换为列表来迭代枚举器:
Where(hero => hero.Faction == "Jedi").ToList()
可能会做你想要的第一个:这给你一个已经代表过滤结果的列表。
但请注意保持懒惰,这在后面非常有用,例如当你构造和嵌套多个像这样的“查询”时。
答案 1 :(得分:1)
您是否希望针对XML进行一些查询?你想要XPath:http://www.w3schools.com/XPath/default.asp&amp; http://www.codeproject.com/KB/cpp/myXPath.aspx
答案 2 :(得分:1)
在WPF中执行此操作的一种简单方法是使用CollectionView而不是原始列表作为ItemsSource。然后,您可以在此设置过滤器,列表控件将仅显示通过过滤器的项目。
但是,听起来您将图像控件直接添加到Panel(Canvas?)而不是使用列表控件。在这种情况下,迭代Image控件并设置其可见性是一种方法。另一种方法是创建一个视图模型类,它使用可见性等显示属性来扩充Hero类,并在用户选择不同的视图按钮时更新该可见性。然后,您的图像控件可以将其可见性数据绑定到视图模型可见性。在视图模型中执行此操作而不是直接操作Image控件的优点是可测试性:对于这样的简单案例而言并不是一件大事,但对于复杂的应用程序而言则越来越重要。
顺便说一句,如果您目前正在手动添加图像但是您的设计还没有设置,我强烈建议使用ItemsControl来调查处理集合的显示。 (请记住,ListBox不仅仅是一个垂直堆栈:您可以使用它来显示您选择的任何布局中的内容。)这将删除大量繁琐的迭代代码!
答案 3 :(得分:0)
如果您不打算使用itowlson建议使用CollectionView
(有利弊),另一种处理方法是在您的班级中添加IsVisible
属性然后实施INotifyPropertyChanged
。然后在WPF中支持show / hide非常容易:
<DataTemplate DataType="{x:Type local:Hero}">
<StackPanel Orientation="Horizontal" IsVisible="{Binding IsVisible}">
<TextBlock Text="{Binding Faction}"/>
<TextBlock Text="{Binding Name}"/>
... etc.
</StackPanel>
</DataTemplate>
<ListBox ItemsSource="{Binding MyDataSource.HeroesCollection}"/>
(您可能会使用Grid
而不是StackPanel
;这只是为了显示DataTemplate
对象的Hero
可能是什么样的。)
IsVisible
属性必须属于Visibility
类型,而不是布尔值,除非您想要实现一个值转换器来将true
转换为Visibility.Visible
和{{ 1}}到false
,例如this guy did。
一旦你这样做,做这样的事情:
Visibility.Collapsed
将像魔术一样工作。 (如果您已实现foreach (Hero h in HeroesCollection)
{
h.IsVisible = h.Faction == selectedFaction
? Visiblity.Visible
: Visibility.Collapsed;
}
。如果您没有实现,则不会发生任何事情,因为UI不会知道INotifyPropertyChanged
属性已更改。)