微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

UserControl WPF 中的 DataContext 绑定

如何解决UserControl WPF 中的 DataContext 绑定

尝试在 UserControl 中获取 DataContext。

我的 structure

我有模型车

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace AutoShop.MVVM.Model
{
    class Car : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged([CallerMemberName] string prop = "")
        {
            PropertyChanged?.Invoke(this,new PropertyChangedEventArgs(prop));
        }


        private string _Model;
        public string Model
        {
            get
            {
                return _Model;
            }
            set
            {
                _Model = value;
                OnPropertyChanged();
            }
        }

        private string _Mark;
        public string Mark
        {
            get
            {
                return _Mark;
            }
            set
            {
                _Mark = value;
                OnPropertyChanged();
            }
        }

        private float _Volume;
        public float Volume
        {
            get
            {
                return _Volume;
            }
            set
            {
                _Volume = value;
                OnPropertyChanged();
            }
        }

        private int _DateOfIssue;
        public int DateOfIssue
        {
            get
            {
                return _DateOfIssue;
            }
            set
            {
                _DateOfIssue = value;
                OnPropertyChanged();
            }
        }

        public enum EngineTypes { 
            disEL,PETROL
        };

        private EngineTypes _EngineType;
        public EngineTypes EngineType
        {
            get
            {
                return _EngineType;
            }
            set
            {
                _EngineType = value;
                OnPropertyChanged();
            }
        }

        private string _ImageUrl;

        public string ImageUrl
        {
            get
            {
                return _ImageUrl;
            }
            set
            {
                _ImageUrl = value;
                OnPropertyChanged();
            }
        }

        public Car()
        {

        }
    }
}

我有主视图模型

using AutoShop.MVVM.Model;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

namespace AutoShop.MVVM.viewmodel
{
    class Mainviewmodel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged([CallerMemberName] string prop = "")
        {
            PropertyChanged?.Invoke(this,new PropertyChangedEventArgs(prop));
        }

        public Homeviewmodel HomeVM; 

        private object _CurrentPage;
        public object CurrentPage
        {
            get
            {
                return _CurrentPage;
            }
            set
            {
                _CurrentPage = value;
                OnPropertyChanged();
            }
        }

        private List<Car> _Cars;

        public List<Car> Cars
        {
            get
            {
                return _Cars;
            }
            set
            {
                _Cars = value;
                OnPropertyChanged();
            }
        }

        public Mainviewmodel()
        {
            Cars = new List<Car>() {
                new Car
                {
                    Mark = "Audi",Model = "asdf",Volume = 1.4F,DateOfIssue = 2019,EngineType = Car.EngineTypes.disEL,ImageUrl = "img/img"
                },new Car
                {
                    Mark = "Moto",new Car
                {
                    Mark = "Some",ImageUrl = "img/img"
                }
            };


            HomeVM = new Homeviewmodel();
            CurrentPage = HomeVM;

        }
    }
}

我需要在 ProductPage.xaml 上展示汽车,然后我通过下一个方式来展示

<UserControl x:Class="AutoShop.MVVM.View.ProductPage"
             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:AutoShop.MVVM.View"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800"
             >
    <StackPanel Background="#fff">
        <WrapPanel>
            <Grid Width="200px" Margin="30 0 0 0">
                <TextBox x:Name="field4" Tag="C:\Users\user\Desktop\Learning\Весенний семестр\ООТП\AutoShop\AutoShop\Images\u.png" Style="{StaticResource TextBoxTemplate}" />
                <TextBlock IsHitTestVisible="False" Text="Марка" Padding="20 10 0 0">
                    <TextBlock.Style>
                        <Style targettype="{x:Type TextBlock}">
                            <Setter Property="Visibility" Value="Collapsed"/>
                            <Setter Property="FontFamily" Value="/Fonts/#Montserrat Light" />
                            <Setter Property="Foreground" Value="#ccc" />
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding Text,ElementName=field4}" Value="">
                                    <Setter Property="Visibility" Value="Visible" />
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </TextBlock.Style>
                </TextBlock>
            </Grid>
            <Grid Width="200px" Margin="30 0 0 0">
                <TextBox x:Name="field7" Tag="C:\Users\user\Desktop\Learning\Весенний семестр\ООТП\AutoShop\AutoShop\Images\u.png" Style="{StaticResource TextBoxTemplate}" />
                <TextBlock IsHitTestVisible="False" Text="username" Padding="20 10 0 0">
                    <TextBlock.Style>
                        <Style targettype="{x:Type TextBlock}">
                            <Setter Property="Visibility" Value="Collapsed"/>
                            <Setter Property="FontFamily" Value="/Fonts/#Montserrat Light" />
                            <Setter Property="Foreground" Value="#ccc" />
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding Text,ElementName=field7}" Value="">
                                    <Setter Property="Visibility" Value="Visible" />
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </TextBlock.Style>
                </TextBlock>
            </Grid>
            <Grid Width="200px" Margin="30 0 0 0">
                <ComboBox Style="{StaticResource ComboBoxTheme}" Selectedindex="0">
                    <ComboBoxItem>
                        <TextBlock Text="asdasdasd" />
                    </ComboBoxItem>
                    <ComboBoxItem>
                        <TextBlock Text="fsdfsd" />
                    </ComboBoxItem>
                </ComboBox>
            </Grid>
        </WrapPanel>
        <Grid Height="400">
            <ScrollViewer VerticalScrollBarVisibility="Auto">
                <ItemsControl x:Name="ItemsWrapper" ItemsSource="{Binding Cars}">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <WrapPanel/>
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <Border Margin="10" BorderBrush="Black" BorderThickness="2" Height="279">
                                <Grid Height="279" Width="200">
                                    <Image Source="{Binding Path=Image}" Width="100" Height="100" VerticalAlignment="Top" Margin="0 10 0 0"  />
                                    <TextBlock Text="{Binding Path=Name,StringFormat='Name: {0}'}" VerticalAlignment="Top" Margin="0,120,0"/>
                                    <TextBlock Text="{Binding Path=Mark,StringFormat='rating: {0}' }" VerticalAlignment="Top" Margin="0 180 0 0" />
                                    <TextBlock Text="{Binding Path=Model,StringFormat='Category: {0}'}" VerticalAlignment="Top" Margin="0,200,0" />
                                    <TextBlock Text="{Binding Path=Volume,StringFormat='Price: {0}'}" VerticalAlignment="Top" Margin="0,160,0" />
                                    <TextBlock Text="{Binding Path=DateOfIssue,StringFormat='Description: {0}'}" VerticalAlignment="Top" Margin="0,140,0" />
                                </Grid>
                            </Border>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
            </ScrollViewer>
        </Grid>
    </StackPanel>
</UserControl>

它是我添加MainForm.xaml ProductPage.xaml

<ContentControl Margin="10" Grid.Column="1" Content="{Binding CurrentPage}"/>

问题是没有输出任何内容,我认为可能是由于丢失了上下文。如何将上下文正确传递给 UserControl (ProductPage.xaml)? ProductPage.xaml

更新: I set DataContext for MainWindow

并且 DataContext 工作,因为 {Binding CurrentPage} 正在工作,但对 Cars 字段的绑定不起作用

解决方法

1.找到MainForm.xaml.cs

2.查找构造函数

public MainForm()
{
    InitializeComponent();
    //set the MainForm DataContext
    DataContext = new MainViewModel();
}

3.你应该添加 ContentControl.DataTemplate 来显示你的 HomeViewModel

----20210427更新

这里是我做的demo,项目名称是WpfApp4

主窗口.xaml

<Window x:Class="WpfApp4.MainWindow"
        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:WpfApp4"
        xmlns:views="clr-namespace:WpfApp4.Views"
        xmlns:viewModels="clr-namespace:WpfApp4.ViewModels"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.DataContext>
        <viewModels:MainWindowViewModel/>
    </Window.DataContext>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <ListBox Grid.Column="0" ItemsSource="{Binding ItemsSource,Mode=OneWay}" SelectedItem="{Binding SelectedCarViewModel,Mode=TwoWay}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Name}"/>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
        <Grid Grid.Column="1">
            <ContentControl Content="{Binding SelectedCarViewModel}">
                <ContentControl.ContentTemplate>
                    <!--Style your product page here-->
                    <DataTemplate DataType="{x:Type viewModels:CarViewModel}">
                        <UniformGrid Columns="2">
                            <TextBlock Text="Name"/>
                            <TextBlock Text="{Binding Name}"/>
                            <TextBlock Text="Volume"/>
                            <TextBlock Text="{Binding Volume}"/>
                            <TextBlock Text="Price"/>
                            <TextBlock Text="{Binding Price}"/>
                        </UniformGrid>
                    </DataTemplate>
                </ContentControl.ContentTemplate>
            </ContentControl>
        </Grid>
    </Grid>
</Window>

MainWindow.xaml.cs

using System.Windows;

namespace WpfApp4
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }
}

MainWindowViewModel.cs

using System.Collections.ObjectModel;

namespace WpfApp4.ViewModels
{
    class MainWindowViewModel : ViewModelBase
    {
        public ObservableCollection<CarViewModel> ItemsSource { get; } = new ObservableCollection<CarViewModel>();

        private CarViewModel selectedCarViewModel;

        public CarViewModel SelectedCarViewModel
        {
            get { return this.selectedCarViewModel; }
            set { SetProperty(ref this.selectedCarViewModel,value); }
        }

        public MainWindowViewModel()
        {
            ItemsSource.Add(new CarViewModel() { Name = "BMW",Volume = 10,Price = 100 });
            ItemsSource.Add(new CarViewModel() { Name = "Toyota",Volume = 5,Price = 80 });
            ItemsSource.Add(new CarViewModel() { Name = "Benz",Volume = 20,Price = 150 });

            // don't let view binding null value,so here initialze property "SelectedCarViewModel"
            this.selectedCarViewModel = ItemsSource[0];
        }
    }
}

CarViewModel.cs

namespace WpfApp4.ViewModels
{
    class CarViewModel : ViewModelBase
    {
        private string name;

        public string Name
        {
            get { return this.name; }
            set { SetProperty(ref this.name,value); }
        }

        private float volume;

        public float Volume
        {
            get { return this.volume; }
            set { SetProperty(ref this.volume,value); }
        }

        private decimal price;

        public decimal Price
        {
            get { return this.price; }
            set { SetProperty(ref this.price,value); }
        }
    }
}

ViewModelBase.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Threading;

namespace WpfApp4.ViewModels
{
    public class ViewModelBase : INotifyPropertyChanged
    {

        public event PropertyChangedEventHandler PropertyChanged;

        protected void RaisePropertyChanged([CallerMemberName] string propertyName = "")
        {
            PropertyChanged?.Invoke(this,new PropertyChangedEventArgs(propertyName));
        }
        
        protected bool SetProperty<T>(ref T t,T value,[CallerMemberName] string propertyName = "")
        {
            if (EqualityComparer<T>.Default.Equals(t,value))
            {
                return false;
            }
            else
            {
                t = value;
                RaisePropertyChanged(propertyName);
                return true;
            }
        }
    }
}
,

将此添加到 Window.Resources。当然,DataContext 必须设置为 MainForm

<Window>
    <Window.Resources>
        <DataTemplate DataType="{x:Type xmlnsForVewModel:MainViewModel}">
            <ProductPage/>
        </DataTemplate>
    </Window.Resources>
</Window>

如果 ProductPage HomeViewModel 应该是 DataContext,那么 HomeViewModel 必须具有 Cars 属性,而不是 MainViewModel

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。