我有一个用wpf构建的条形图。用户指定栏内的项目。
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()
{
}
}
要添加新的BarChart,请运行
<local:BarChart>
<local:BarChart.Items>
<local:BarItem Lable="B" Value="75"/>
<local:BarItem Lable="A" Value="50"/>
</local:BarChart.Items>
</local:BarChart>
然而根据输出,没有添加任何项目。我做错了什么,有更好的方法吗?
答案 0 :(得分:2)
你的问题是属性设置器实际上从未被调用过。
按照您在XAML中的方式添加BarItem对象,将项目添加到现有列表实例。只有在将列表设置为新实例时才会调用属性设置器。
所以我会在代码隐藏中创建一个新列表,并在那里设置属性。这样做会调用setter,你的代码就会运行。您可能需要为BarChart命名,以便您可以参考它。
<强> 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>
<强>代码隐藏强>
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 }
};
}
答案 1 :(得分:2)
此外,我认为您可以使用ObservableCollection<BarItem>
执行此操作,然后注册到事件CollectionChanged
以控制插入和删除。
但我认为正确的方法是使用DependencyProperty
ICollection
,然后如果集合实现ICollectionChanged
接口,您可以控制插入和删除以更新如果您想要对此集合进行绑定,这应该非常有用。
希望这对你有帮助,......
答案 2 :(得分:1)
我会用Binding做到这一点。代码隐藏只是持有一个属性:
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();
}
}
虽然UI会做其余的事情:
<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>
用户界面中发生了哪些变化:
ItemsControl
不同,Grid
具有有用的ItemsSource
属性,这使事情变得更容易; StackPanel
不同,Grid
无需通过堆叠项目手动定位项目。如果您希望项目之间存在差距,可以将local:Bar Margin
设置为常量值。