WPF:在XAML和代码后台中设置ItemSource的区别

7

由于这是WPF,可能需要写很多代码,但不要被吓倒,问题实际上很简单!

我有以下XAML:

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:hax="clr-namespace:hax" x:Class="hax.MainWindow"
    x:Name="Window" Title="Haxalot" Width="640" Height="280">

    <Grid x:Name="LayoutRoot">
        <ListView ItemsSource="{Binding AllRoles}" Name="Hello">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Name"
                       DisplayMemberBinding="{Binding Path=FullName}"/>
                    <GridViewColumn Header="Role"
                       DisplayMemberBinding="{Binding Path=RoleDescription}"/>
                </GridView>
            </ListView.View>
        </ListView> 
    </Grid>
</Window>

我有这个代码后台:

using System.Collections.ObjectModel;
using System.Windows;

namespace hax
{

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {

        public ObservableCollection<Role> AllRoles { get { return m_AllRoles; } set { m_AllRoles = value; } }
        private ObservableCollection<Role> m_AllRoles = new ObservableCollection<Role>();

        public MainWindow()
        {
            this.InitializeComponent();

            AllRoles.Add(new Role("John", "Manager"));
            AllRoles.Add(new Role("Anne", "Trainee"));
            // Hello.ItemsSource = AllRoles; // NOTE THIS ONE!
        }
    }
}

如果我注释掉语句Hello.ItemSource = AllRoles,那么表格将不会显示任何内容。当我取消注释后,它会显示正确的内容。为什么会这样呢?
2个回答

16

这个:

<ListView ItemsSource="{Binding AllRoles}" Name="Hello">

意思是将ItemsSource绑定到属性this.DataContext.AllRoles,其中this是当前元素。

Hello.ItemsSource = AllRoles;

意思是将ItemsSource绑定到一个充满角色的ObservableCollection<T>,这直接实现了你最初想要做的事情。

XAML中有许多方法可以实现这一点。以下是其中一种:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        this.InitializeComponent();
        var allRoles = new ObservableCollection<Role>()
        allRoles.Add(new Role("John", "Manager"));
        allRoles.Add(new Role("Anne", "Trainee"));
        this.DataContext = allRoles;
    }
}

在XAML中

<ListView ItemsSource="{Binding}" Name="Hello">

或者,你可以将AllRoles作为窗口的公共属性

public partial class MainWindow : Window
{
    public ObservableCollection<Role> AllRoles {get;private set;}
    public MainWindow()
    {
        this.InitializeComponent();
        var allRoles = new ObservableCollection<Role>()
        allRoles.Add(new Role("John", "Manager"));
        allRoles.Add(new Role("Anne", "Trainee"));
        this.AllRoles = allRoles;
    }
}

然后使用RelativeSource告诉绑定器向上遍历逻辑树到窗口

<ListView 
  ItemsSource="{Binding AllRoles, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" 
  Name="Hello">

这意味着“查看我的祖先,直到找到一个窗口,然后查找窗口上名为AllRoles的公共属性。”

但最好的方法是完全跳过 **codebehind**,使用MVVM模式。 如果您正在学习,我建议您直接跳转到MVVM模式。 学习曲线陡峭,但您将了解有关绑定和命令以及WPF的重要和酷炫功能。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接