c# - UserControl WPF 中的 DataContext 绑定
问题描述
试图在 UserControl 中获取 DataContext。
我的 结构
我有模型车
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",
Model = "asdf",
Volume = 1.4F,
DateOfIssue = 2019,
EngineType = Car.EngineTypes.DISEL,
ImageUrl = "img/img"
},
new Car
{
Mark = "Some",
Model = "asdf",
Volume = 1.4F,
DateOfIssue = 2019,
EngineType = Car.EngineTypes.DISEL,
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,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,0" />
<TextBlock Text="{Binding Path=Volume, StringFormat='Price: {0}'}" VerticalAlignment="Top" Margin="0,160,0,0" />
<TextBlock Text="{Binding Path=DateOfIssue, StringFormat='Description: {0}'}" VerticalAlignment="Top" Margin="0,140,0,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)? 产品页面.xaml
更新: 我为 MainWindow 设置 DataContext
并且 DataContext 工作{Binding CurrentPage}
,因为正在工作,但在 Cars 字段上的绑定不起作用
解决方案
1.找到MainForm.xaml.cs
2.查找ctor
public MainForm()
{
InitializeComponent();
//set the MainForm DataContext
DataContext = new MainViewModel();
}
3.你应该添加 ContentControl.DataTemplate 来显示你的 HomeViewModel
----20210427更新
这是我做的演示,项目名称是 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>
主窗口.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;
}
}
}
}
推荐阅读
- mysql - 将 SQL 行合二为一
- html - 如何在 bootstrap 4 中添加范围滑块模型?
- android - 带有 Xamarin 表单的 Google 移动视觉
- database - 博客内容如何存储在数据库中?
- javascript - 我不允许显示来自新版本 (v2) 的 aDribbble API 的数据
- html - 使用express时没有加载angularjs
- asp.net - http.GET 有效,但 http.post 和 http.put 无效
- eigen - Hermitian 矩阵的 Eigen 中的 ConjugateGradient
- electron - 在 Electron React 应用程序中包含 Bootstrap
- c# - Xamarin.Forms - 使用活动状态关闭 ActivityIndicator