数据绑定到WrapPanel不能按预期工作

时间:2013-04-29 14:43:07

标签: wpf data-binding mvvm wrappanel

我正在尝试使用我自己的用户控件集合填充WrapPanel

儿童控制:

<UserControl x:Class="MyApplication.StockMappings.StockView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid Width="140" Height="80">
        <Border CornerRadius="6" BorderBrush="Black" BorderThickness="2" >
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="0.6*"/>
                    <RowDefinition Height="0.4*"/>
                </Grid.RowDefinitions>
                <TextBlock Grid.Row="0" FontSize="18" FontWeight="Bold">
                    <Label Content="{Binding Path=ID}"/>
                </TextBlock>
                <TextBlock Grid.Row="1" FontSize="12" FontWeight="Bold">
                    <Label Content="{Binding Path=StockName}"/>
                </TextBlock>
            </Grid>
        </Border>
    </Grid>
</UserControl>

cs文件:

namespace MyApplication.StockMappings
{
    /// <summary>
    /// Interaction logic for StockView.xaml
    /// </summary>
    public partial class StockView : UserControl
    {
        public StockView()
        {
            InitializeComponent();
        }

        public string ID
        {
            get;
            set;
        }

        public string StockName
        {
            get;
            set;
        }
    }
}

最后,带有包裹面板的窗口:

<Window x:Class="MyApplication.StockMappings.TestWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:MyApplication.StockMappings"
        Title="TestWindow" Height="300" Width="300">
    <Grid>
        <ItemsControl Name="Stocks" ItemsSource="{Binding AllStocks}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <WrapPanel Orientation="Horizontal"/>                        
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <local:StockView/>                                            
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </Grid>
</Window>

再次使用C#代码:

public partial class TestWindow : Window
{
    public TestWindow()
    {
        InitializeComponent();
        var stocks = new[]
        {
            new StockView() { ID = "M0", StockName = "abc"},
            new StockView() { ID = "M1", StockName = "def"},
        };

        Stocks.DataContext = new Test()
        {
            AllStocks = stocks.ToList()
        }; 
    }
}

Test类(子数据的容器)非常简单:

public class Test
{
    public List<StockView> AllStocks
    {
        get;
        set;
    }
}

最后,结果:

screenshot

所有边框都是空白的。 <{1}}和ID均未显示。

我做错了什么?

我已确认(通过添加虚拟属性)StockName控件从StockView对象获取ID值,而不是Test列表中的子项。但为什么?我没有定义AllStocks吗?那是什么呢?

4 个答案:

答案 0 :(得分:2)

您缺少的是保存数据的适当视图模型项类。这不应该与视图对象混淆,例如你的StockView。

首先,从StockView控件中删除IDStockName属性。这些属性将移至数据项类。

public partial class StockView : UserControl
{
    public StockView()
    {
        InitializeComponent();
    }
}

其次,创建一个包含StockItem数据项类的视图模型,以及一个具有ViewModel属性的AllStocks类(或者只调用它Test所做的那样)。

public class StockItem
{
    public string ID { get; set; }
    public string StockName { get; set; }
}

public class ViewModel
{
    public ObservableCollection<StockItem> AllStocks { get; set; }
}

最后,将MainWindow的DataContext设置为ViewModel类的实例。

public MainWindow()
{
    InitializeComponent();

    var vm = new ViewModel { AllStocks = new ObservableCollection<StockItem>() };
    vm.AllStocks.Add(new StockItem { ID = "M0", StockName = "abc" });
    vm.AllStocks.Add(new StockItem { ID = "M1", StockName = "def" });

    DataContext = vm;
}

如果数据项在添加到AllStocks集合后可以修改,StockItem类必须实现INotifyPropertyChanged接口。

答案 1 :(得分:1)

嗯,DataContext usercontrol的StockView应该是它自己的代码。

这应该会有效!

public StockView()
{
    InitializeComponent();
    this.DataContext = this;
}

答案 2 :(得分:1)

设置用户控件的datacontext 例如在代码中:

public StockView()
        {
            InitializeComponent();
            DataContext = this;
        }

答案 3 :(得分:1)

DataTemplates模板数据,您绑定到控件列表,ItemTemplate将被忽略,因为可以直接添加控件,您应该在输出中收到关于此的警告。因此,DataContext没有设置UserControls,您应该将属性从UserControl移动到模型类并添加其实例。另外,我建议不要设置DataContext的{​​{1}}。