从UserControls设置WPF DataContext

时间:2015-12-27 23:12:35

标签: c# wpf xaml data-binding binding

大家好,我已经搜索了很长时间,但我无法解决这个问题:

我想在我的主窗口的Listbox中为ProductList中的每个元素提供一个显示一些内容的UserControl。

我的MainWindow XAML代码:

<Window
        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:CigaretteAutomation"
        xmlns:UserControls="clr-namespace:CigaretteAutomation.UserControls" x:Class="CigaretteAutomation.MainWindow"
        mc:Ignorable="d"
        Title="HB Sparverein Wiesinger - Zigaretten" WindowState="Maximized">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions></TextBlock>
        <ListBox x:Name="lb" Grid.Row="1" Width="Auto" Margin="10" ItemsSource="{Binding ProductList}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel>
                        <UserControls:UserControlDisplayProduct DataContext="{Binding ProductList/}"></UserControls:UserControlDisplayProduct>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
        <Button x:Name="btLogin" Grid.Row="2" Content="Button" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Click="btLogin_Click"/>
    </Grid>
</Window>

我的MainWindow XAML.cs文件:

namespace CigaretteAutomation
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            ViewModelMainWindow vm = new ViewModelMainWindow();
            InitializeComponent();
            this.DataContext = vm; 
         }

    }
}

我的MainWindow的ViewModel(用于DC):

namespace CigaretteAutomation.ViewModelWindow
{
    public class ViewModelMainWindow
    {
        public ViewModelMainWindow()
        {
            ProductList = new ObservableCollection<ViewModelProduct>();
            // Get all DB Entities
            using (CIGARETTES_DBEntities c = new CIGARETTES_DBEntities())
            {
                foreach (PRODUCT productFromDB in c.PRODUCTS)
                {
                    ViewModelProduct vmProd = new ViewModelProduct(productFromDB);
                    ProductList.Add(vmProd);

                }
            } 

        }

        public ObservableCollection<ViewModelProduct> ProductList { get; set; }
    }
}

那是我的Usercontrol XAML文件:

<UserControl x:Class="CigaretteAutomation.UserControls.UserControlDisplayProduct"
             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" 
             xmlns:local="clr-namespace:CigaretteAutomation.UserControls"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <DockPanel>
        <TextBlock DockPanel.Dock="Top" HorizontalAlignment="Center" Text="IMG" FontSize="40" VerticalAlignment="Center"/>
        <TextBlock DockPanel.Dock="Bottom" HorizontalAlignment="Center" Text="{Binding Name}"/>
        <TextBlock DockPanel.Dock="Bottom" HorizontalAlignment="Center" Text="{Binding Price}" VerticalAlignment="Bottom"/>
    </DockPanel>
</UserControl>

最后我的产品ViewModel:

namespace CigaretteAutomation.ViewModelData
{
    public class ViewModelProduct : INotifyPropertyChanged
    {
        public ViewModelProduct(PRODUCT _productFromDB)
        {
            ProductFromDB = _productFromDB;
            _name = ProductFromDB.NAME;
            _price = ProductFromDB.PRICE.ToString();
        }

        public PRODUCT ProductFromDB;

        private string _name;
        public string Name { get { return _name; } set { this.ChangeAndNotify(ref _name, value); } }

        private string _price;
        public string Price { get { return _price; } set { this.ChangeAndNotify(ref _price, value); } }

        // Notifying

        public event PropertyChangedEventHandler PropertyChanged;
        public event PropertyChangingEventHandler PropertyChanging;

        public bool ChangeAndNotify<T>(ref T field, T value, [CallerMemberName] string propertyName = null, IEqualityComparer comparer = null)
        {
            if (IsEqual(field, value, comparer))
                return false;
            if (PropertyChanging == null && PropertyChanged == null)
                field = value;
            else
            {
                OnPropertyChanging(propertyName);
                field = value;
                OnPropertyChanged(propertyName);
            }
            return true;
        }

        private bool IsEqual<T>(T field, T value, IEqualityComparer comparer)
        {
            IEqualityComparer cmp = comparer ?? EqualityComparer<T>.Default;
            return cmp.Equals(field, value);
        }

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            if (this.PropertyChanged != null)
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
        protected virtual void OnPropertyChanging([CallerMemberName] string propertyName = null)
        {
            if (this.PropertyChanging != null)
                this.PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
        }

    }
}

对不起,我知道到目前为止有相当多的代码......

我的问题是我无法绑定到ProductList中的元素。它始终显示为空...

我已经尝试使用绑定的RelativeSource Self,但它也没有用。我觉得有点困惑的是,我的ProductList中的所有2个项目都显示了元素,但没有显示控件中的属性。

有没有人能解决这个问题?迎接!

1 个答案:

答案 0 :(得分:1)

您可以通过从Datatemplate删除DataContext绑定来修复它:

<ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel>
                        <UserControls:UserControlDisplayProduct/>
                    </StackPanel>
                </DataTemplate>

每个产品Item都已经通过Product的枚举实例获取相关的datacontext。这就是基于多个项目的控件的工作方式。