简体   繁体   English

WPF / XAML:UserControls的数据绑定

[英]WPF / XAML: Data Binding for UserControls

So I'm creating "cards" to visually represent a collection of objects within a StackPanel (which I'm using a list to hold these objects): 因此,我正在创建“卡片”以直观地表示StackPanel中的对象集合(我正在使用列表来保存这些对象):

MainWindow XAML: MainWindow XAML:

<Window /* ... */>
    <StackPanel x:Name="Deck" Orientation="Horizontal" />
</Window>

MainWindow C#: MainWindow C#:

public partial class MainWindow : Window
{
    /* ... */
    private void OnDataReceived(List<Reading> readings)
    {
        foreach(Reading r in readings)
        {
            Deck.Children.Add(new Card
            {
                Id = r.Id,
                Value = r.Value
            });
        }
    }
}

UserControl XAML: UserControl XAML:

<UserControl /* ... */ x:Name="crd">
    <Label Content="{Binding Path=Id, ElementName=crd}" />
    <Label Content="{Binding Path=Value, ElementName=crd} />
</UserControl>

UserControl C#: UserControl C#:

public partial class LoggerRepresentation : UserControl
{
    public string Id { get; set; }
    public int Value { get; set; }
    /* ... */
}

Upon adding one element to Deck.Children , its' visual representation does appear in the StackPanel as expected. Deck.Children添加一个元素Deck.Children ,其视觉表示确实如预期的那样出现在StackPanel中。 However, DP seems to lack something as the Labels binding Id and Value remain empty. 但是,DP似乎缺少某些东西,因为标签绑定IdValue保持为空。

(The idea to give x:Name="crd" to my UserControl and then use it within the Binding as ElementName has been plugged from the answer to a seemingly related question , but may be misleading in this case.) (将x:Name="crd"分配给我的UserControl,然后在Binding中将其用作ElementName的想法已经从一个看似相关的问题的答案中插入 ,但是在这种情况下可能会引起误解。)

You should use an ItemsControl whenever you want to display a dynamic collection of items. 每当您要显示项目的动态集合时,都应使用ItemsControl

Replace the StackPanel in your XAML markup with an 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>

Bind directly to the source properties of the corresponding Card object in the UserControl (and replace the Label elements with TextBlocks ): 直接绑定到UserControl相应Card对象的源属性(并将Label元素替换为TextBlocks ):

<TextBlock Text="{Binding Path=Id}" />
<TextBlock Text="{Binding Path=Value} />

Create a view model class that exposes a collection of Card objects through a public property and move your application logic over to this one: 创建一个视图模型类,该视图模型类通过公共属性公开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
            });
        }
    }
}

Set the DataContext of the view where the ItemsControl is defined to an instance of the view model class: 将定义了ItemsControl的视图的DataContext设置为视图模型类的实例:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = new ViewModel();
    }
}

This design pattern is known as Model-View-ViewModel (MVVM) and it's the recommended pattern to use when developing XAML based UI applications. 这种设计模式被称为模型-视图-视图模型(MVVM),它是在开发基于UI应用程序XAML使用推荐模式。 You will find a lot more to read and learn about it if your Google. 如果您使用的是Google,那么您会发现更多阅读和了解的内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM