簡體   English   中英

UserControl WPF 中的 DataContext 綁定

[英]DataContext binding in UserControl WPF

試圖在 UserControl 中獲取 DataContext。

我的結構

我有 model 車

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()
        {

        }
    }
}

我有主視圖 model

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;
            }
        }
    }
}

將此添加到Window.Resources 當然DataContext必須為MainForm設置。

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

如果ProductPage HomeViewModel應該是DataContext ,那么HomeViewModel必須有Cars屬性,而不是MainViewModel

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM