C# WPF/XAML:用户控件的数据绑定
因此,我正在创建“卡片”,以直观地表示StackPanel中的对象集合(我使用列表来保存这些对象): 主窗口XAML:C# WPF/XAML:用户控件的数据绑定,c#,wpf,xaml,data-binding,C#,Wpf,Xaml,Data Binding,因此,我正在创建“卡片”,以直观地表示StackPanel中的对象集合(我使用列表来保存这些对象): 主窗口XAML: <Window /* ... */> <StackPanel x:Name="Deck" Orientation="Horizontal" /> </Window> 在向Deck.Children添加一个元素后,其“视觉表示”确实会按预期显示在StackPanel中。然而,由于绑定Id和Value的标签仍然为空,DP似乎缺少一些东西
<Window /* ... */>
<StackPanel x:Name="Deck" Orientation="Horizontal" />
</Window>
在向Deck.Children
添加一个元素后,其“视觉表示”确实会按预期显示在StackPanel中。然而,由于绑定Id
和Value
的标签仍然为空,DP似乎缺少一些东西
(将
x:Name=“crd”
赋予my UserControl,然后作为ElementName
在绑定中使用它的想法已被插入,但在这种情况下可能会产生误导。)无论何时要显示项的动态集合,都应该使用ItemsControl
将XAML标记中的StackPanel
替换为ItemsControl
:
<ItemsControl ItemsSource="{Binding Cards}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:LoggerRepresentation />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
创建一个视图模型类,该类通过公共属性公开一组Card
对象,并将应用程序逻辑移到此类:
public class ViewModel
{
public ObservableCollection<Card> Cards { get; } = new ObservableCollection<Card>();
//...
private void OnDataReceived(List<Reading> readings)
{
foreach (Reading r in readings)
{
Cards.Add(new Card
{
Id = r.Id,
Value = r.Value
});
}
}
}
这种设计模式称为模型-视图-视图-模型(MVVM),是开发基于XAML的UI应用程序时推荐使用的模式。如果你在谷歌上搜索,你会发现更多的东西可以阅读和学习。看起来你正在做的事情和以前在windows编程中做的一样。您应该检查MVVM和INotifyPropertyChanged接口。
不允许在
中使用,但在我将模板标记包装到
中时可以使用。这是正确的吗?我似乎还是弄错了,至少我现在的输出有错误:System.Windows.Data错误:40:BindingExpression路径错误:“在”“对象”“视图模型”(HashCode=2077076)上找不到“值”属性。BindingExpression:Path=Value;DataItem='ViewModel'(HashCode=2077076);目标元素为“TextBlock”(名称=“”);目标属性为“Text”(类型为“String”)
是
中的“Cards”,引用公共ObservableCollection Cards中的“Cards”{get;}=new ObservableCollection()代码>?除非你在某个地方覆盖了DataContext,否则我仍然无法理解它应该是什么样子。我现在应该如何从主窗口向列表中添加项目呢?我在ViewModel类中添加了一个函数“Add()”,我只是将收到的项目路由到Cards属性中。对吗?你应该使用命令。但那是另一个故事。如果您有其他问题,请提出新问题。
public partial class LoggerRepresentation : UserControl
{
public string Id { get; set; }
public int Value { get; set; }
/* ... */
}
<ItemsControl ItemsSource="{Binding Cards}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:LoggerRepresentation />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<TextBlock Text="{Binding Path=Id}" />
<TextBlock Text="{Binding Path=Value} />
public class ViewModel
{
public ObservableCollection<Card> Cards { get; } = new ObservableCollection<Card>();
//...
private void OnDataReceived(List<Reading> readings)
{
foreach (Reading r in readings)
{
Cards.Add(new Card
{
Id = r.Id,
Value = r.Value
});
}
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new ViewModel();
}
}