Simple WPF data binding question with icons
I have a few types that make up a hierarchy like this:
+ Image0.Name
Effect0.Name
Effect1.Name
Effect2.Name
Layer0.Name
Layer1.Name
Layer2.Name
...
+ Image1.Name
Effect0.Name
Effect1.Name
Effect2.Name
Layer0.Name
Layer1.Name
Layer2.Name
...
+ Image2.Name
Effect0.Name
Effect1.Name
Effect2.Name
Layer0.Name
Layer1.Name
Layer2.Name
...
But I can't get my head around the data binding. Here is the code for the types:
public class Image
{
public string Name { get; set; }
public IEnumerable<Effect> Effects { get; set; }
public IEnumerable<Layer> Layers { get; set; }
}
public class Effect
{
public string Name { get; set; }
public Effect ( string name )
{
this.Name = name;
}
}
public class Layer
{
public string Name { get; set; }
public Layer ( string name )
{
this.Name = name;
}
}
public class EditorView : INotifyPropertyChanged
{
IEnumerable&l开发者_JS百科t;Node> images;
public IEnumerable<Node> Images
{
get { return images; }
set
{
this.images = value;
this.RaisePropertyChanged ( "Images" );
}
}
public event PropertyChangedEventHandler PropertyChanged;
void RaisePropertyChanged ( string propertyName )
{
var handler = this.PropertyChanged;
if ( handler != null )
handler ( this, new PropertyChangedEventArgs ( propertyName ) );
}
}
Additionally these types (Effect
, Layer
) has a unique icon per type, if you can also show how to bind this, that would help me a lot in understanding it all.
This is how I normally do it, create a base class for the child items and then create I property that returns all the child Items
public class Image
{
public string Name { get; set;}
public IEnumerable<Effect> Effects { get; set; }
public IEnumerable<Layer> Layers { get; set; }
public IEnumerable<Node> Nodes { get { return ((IEnumerable<Node>)Layers).Union((IEnumerable<Node>)Effects); } }
}
public class Effect : Node
{
public Effect(string name)
{
this.Name = name;
}
}
public class Layer : Node
{
public Layer(string name) { this.Name = name; }
}
public class Node
{
public string Name { get; set; }
public Image Icon { get; set; }
}
You should be able to set the Image Property (url of image but you can change the property type) of the respective Effects and Layers and then I've already wired it up, this should work
<TreeView Height="221" HorizontalAlignment="Left" Margin="12,12,0,0" Name="treeView1"
VerticalAlignment="Top" Width="479" ItemsSource="{Binding Images}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Nodes}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}"></TextBlock>
<Image Source="{Binding Icon}"></Image>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
EDIT
And then set the TreeView Item's DataContext to your ViewModel, just as an example I did this in the code behind:
Image img = new Image();
Effect effect = new Effect("Effect1");
Layer layer = new Layer("Layer1");
img.Name = "Image1";
List<Effect> effects = new List<Effect>();
effects.Add(effect);
img.Effects = effects;
List<Layer> layers = new List<Layer>();
layers.Add(layer);
img.Layers = layers;
List<WpfApplication1.Image> Images = new List<Image>();
Images.Add(img);
EditorView ev = new EditorView();
ev.Images = Images;
treeView1.DataContext = ev;
EDIT2: Pasted complete code (without using statements):
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new EditorView();
}
}
public class Image
{
public string Name { get; set;}
public IEnumerable<Effect> Effects { get; set; }
public IEnumerable<Layer> Layers { get; set; }
public IEnumerable<Node> Nodes { get { return ((IEnumerable<Node>)Layers).Union((IEnumerable<Node>)Effects); } }
}
public class Effect : Node
{
public Effect(string name)
{
this.Name = name;
}
}
public class Layer : Node
{
public Layer(string name) { this.Name = name; }
}
public class Node
{
public string Name { get; set; }
public string Icon { get; set; }
}
public class EditorView : INotifyPropertyChanged
{
public EditorView()
{
Image img = new Image();
WpfApplication1.Effect effect = new WpfApplication1.Effect("Effect1");
WpfApplication1.Layer layer = new Layer("Layer1");
img.Name = "Image1";
List<Effect> effects = new List<WpfApplication1.Effect>();
effects.Add(effect);
img.Effects = effects;
List<Layer> layers = new List<Layer>();
layers.Add(layer);
img.Layers = layers;
List<WpfApplication1.Image> Images = new List<Image>();
Images.Add(img);
this.Images = Images;
}
IEnumerable<Image> images;
public IEnumerable<Image> Images
{
get
{
return images;
}
set { this.images = value; this.RaisePropertyChanged("Images");
}
} public event
PropertyChangedEventHandler
PropertyChanged;
void RaisePropertyChanged(string propertyName)
{ var handler = this.PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
You need to implement the HierarchicalDataTemplate. For sample of it look at the last of this article - http://msdn.microsoft.com/en-us/library/ms742521.aspx and this one - http://blogs.msdn.com/b/chkoenig/archive/2008/05/24/hierarchical-databinding-in-wpf.aspx
精彩评论