Reputation: 585
I have a bar chart which is built in wpf. The user specifies the items inside the bar.
BarChart.xaml.cs
public partial class BarChart : UserControl
{
List<BarItem> BarItems = new List<BarItem>();
List<Bar> Bars = new List<Bar>();
public List<BarItem> Items
{
get { return BarItems; }
set
{
BarItems = value;
Bars.Clear();
int i=0;
this.LayoutRoot.Children.Clear();
//This line should show up but doesn't suggesting that that the property is not being set?
Debug.WriteLine("SET");
foreach(BarItem Item in BarItems){
Bar ThisBar=new Bar();
ThisBar.CurrentLable=Item.Lable;
ThisBar.CurrentValue=Item.Value;
Debug.WriteLine("{0}:{1} at {2}",Item.Lable,Item.Value,(i*55));
ThisBar.CurrentX=i*55;
this.AddChild(ThisBar);
i++;
}
Debug.WriteLine(i);
}
}
public BarChart()
{
this.InitializeComponent();
}
}
BarChart.xaml
<UserControl
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:CipherCracker"
mc:Ignorable="d"
x:Class="CipherCracker.BarChart"
x:Name="BarChartList"
d:DesignWidth="640" d:DesignHeight="480">
<Grid x:Name="LayoutRoot"/>
</UserControl>
BarItem.cs
public class BarItem
{
public int Value
{
get;
set;
}
public string Lable
{
get;
set;
}
public BarItem()
{
}
}
To add a new BarChart you run
<local:BarChart>
<local:BarChart.Items>
<local:BarItem Lable="B" Value="75"/>
<local:BarItem Lable="A" Value="50"/>
</local:BarChart.Items>
</local:BarChart>
Yet according to the output no items have been added. What am I doing wrong and is there a better way?
Upvotes: 1
Views: 1979
Reputation: 4760
Also i think you could do this using an ObservableCollection<BarItem>
and then register to the event CollectionChanged
for controlling the insertions and deletes.
But I think the right way for doing this, is using a DependencyProperty
of ICollection
, then if the collection implements the ICollectionChanged
interface you could control the insertion and deletions for updating the view.This should be very useful if you may want make bindings to this collection.
Hope this could helps to you,...
Upvotes: 2
Reputation: 5736
I would do that with Binding. The code-behind would be just holding a property:
public partial class BarChart : UserControl
{
private List<BarItem> _items;
public List<BarItem> Items
{
get { return _items ?? (_items = new List<BarItem>()); }
set { _items = value; }
}
public BarChart()
{
InitializeComponent();
}
}
While UI would be doing the rest:
<ItemsControl ItemsSource="{Binding Items, ElementName=BarChartList}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:Bar CurrentLable={Binding Lable} CurrentValue={Binding Value}/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
What has been changed in UI:
ItemsControl
, unlike Grid
, has useful ItemsSource
property, which makes things easier;StackPanel
, unlike Grid
, eliminates the need to position items manually by stacking them. You can set local:Bar Margin
to a constant value if you want to have a gap between the items.Upvotes: 1
Reputation: 8907
Your problem is that the property setter never actually is being called.
Adding the BarItem objects the way you are doing in XAML, will add the items to the existing list instance. The property setter is only being called when you set the list to a new instance.
So I would create a new list in the code-behind, and set the property there. Doing that will call the setter, and your code will run. You might need to give the BarChart a name so you can reference it.
XAML
<local:BarChart x:Name="bar">
<!-- Doing this adds BarItems to the existing list.
<local:BarChart.Items>
<local:BarItem Lable="B" Value="75"/>
<local:BarItem Lable="A" Value="50"/>
</local:BarChart.Items>
-->
</local:BarChart>
Code-behind
public MainWindow()
{
InitializeComponent();
//Setting the Items property to a new list, will call the setter..
bar.Items = new List<BarItem>
{
new BarItem { Lable = "Test1", Value = 500 },
new BarItem { Lable = "Test2", Value = 1000 },
new BarItem { Lable = "Test3", Value = 1500 }
};
}
Upvotes: 2