【问题标题】:Using bound data in DataTemplate在 DataTemplate 中使用绑定数据
【发布时间】:2016-03-21 22:55:51
【问题描述】:

我有一个我正在使用 DataTemplate 装饰的 CustomWindow.cs,因为有大量的内容变化。根据 MVVM,窗口的 DataContext 绑定到 ViewModel

理想情况下,其中一些装饰将使用来自 ViewModel 的数据进行填充。

我想要实现的结构如下:

<CustomWindow DataContext="{Binding Main, Source={StaticResource Locator}}">
  <Content>
</CustomWindow>

DataTemplate 可能类似于:

<DataTemplate DataType="{x:Type CustomWindow}">
    <ContentPresenter Content="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type viewModels:HmiViewModelBase}}}">
        <ContentPresenter Content="{Binding Content}"/>
    </ContentPresenter>
</DataTemplate>

我意识到 ContentPresenter 中 Content 的双重定义行不通,但想不出替代方案。

我将如何实现这样的目标? 我觉得这将是一个常见问题。

【问题讨论】:

    标签: wpf xaml mvvm data-binding datacontext


    【解决方案1】:

    首先欢迎来到 SO。请看下一个概念:1)一个主视图模型包含一些可观察集合(或基于绑定和属性)中的多个模型。 2)可观察集合中的每个模型都有自己的逻辑,并且应该以某种原始方式呈现。 3)主视图模型由主视图(比如说列表框)呈现。 4)主视图模型的可观察集合内的每个模式都由内容控件呈现,内容控件将为其内容选择一些原始内容模板(这是可观察集合内的模型)。 5)基于模型类型的数据模板可以使用每个wpf控件(或您制作的用户自定义控件)并呈现数据。这是代码: 1. XAML 代码:

    <Window x:Class="DataTemplateSOHelpAttempt.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:dataTemplateSoHelpAttempt="clr-namespace:DataTemplateSOHelpAttempt"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <dataTemplateSoHelpAttempt:MainViewModel/>
    </Window.DataContext>
    <Window.Resources>
        <DataTemplate DataType="{x:Type dataTemplateSoHelpAttempt:OrangeObject}">
            <TextBlock Text="{Binding Description}" Background="Orange"></TextBlock>
        </DataTemplate>
        <DataTemplate DataType="{x:Type dataTemplateSoHelpAttempt:GreenObject}">
            <TextBlock Text="{Binding Description}" Background="GreenYellow"></TextBlock>
        </DataTemplate>
        <DataTemplate DataType="{x:Type dataTemplateSoHelpAttempt:BlueObject}">
            <TextBlock Text="{Binding Description}" Background="CadetBlue"></TextBlock>
        </DataTemplate>
    </Window.Resources>
    <Grid>
        <ListBox ItemsSource="{Binding Objects}">
            <ListBox.ItemContainerStyle>
                <Style TargetType="ListBoxItem">
                    <Setter Property="ContentTemplate">
                        <Setter.Value>
                            <DataTemplate>
                                <ContentControl Content="{Binding }"/>
                            </DataTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </ListBox.ItemContainerStyle>
        </ListBox>
    </Grid></Window>
    

    2。查看型号代码:

    public class MainViewModel:BaseObservableObject
    {
        public MainViewModel()
        {
            Objects = new ObservableCollection<BaseDataObject>(new List<BaseDataObject>
            {
                new BlueObject{Description = "Hello I'm blue object!!!"},
                new OrangeObject{Description = "Hello I'm orange object!!!"},
                new GreenObject{Description = "Hello I'm green object!!!"},
                new OrangeObject{Description = "Hello I'm anoter orange object!!!"},
                new BlueObject{Description = "Hello I'm another blue object!!!"},
                new OrangeObject{Description = "Hello I'm another orange again object!!!"},
                new GreenObject{Description = "Hello I'm another green object!!!"},
                new OrangeObject{Description = "Hello I'm again another orange object!!!"},
            });
        }
        public ObservableCollection<BaseDataObject> Objects { get; set; }
    }
    

    3。型号代码:

    public abstract class BaseDataObject:BaseObservableObject
    {
        public abstract string Description { get; set; }
    }
    
    public class OrangeObject:BaseDataObject
    {
        private string _description;
    
        public override string Description
        {
            get { return _description; }
            set
            {
                _description = value;
                OnPropertyChanged();
            }
        }
    }
    
    public class BlueObject:BaseDataObject
    {
        private string _description;
    
        public override string Description
        {
            get { return _description; }
            set
            {
                _description = value;
                OnPropertyChanged();
            }
        }
    }
    
    public class GreenObject:BaseDataObject
    {
        private string _description;
    
        public override string Description
        {
            get { return _description; }
            set
            {
                _description = value;
                OnPropertyChanged();
            }
        }
    }
    

    4。基本 INotifyPropertyChanged 实现(CallerMemberName 使用 4.5 dotNet 版本):

     public class BaseObservableObject : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
    
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            var handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
    
        protected virtual void OnPropertyChanged<T>(Expression<Func<T>> raiser)
        {
            var propName = ((MemberExpression)raiser.Body).Member.Name;
            OnPropertyChanged(propName);
        }
    
        protected bool Set<T>(ref T field, T value, [CallerMemberName] string name = null)
        {
            if (!EqualityComparer<T>.Default.Equals(field, value))
            {
                field = value;
                OnPropertyChanged(name);
                return true;
            }
            return false;
        }
    }
    

    就是这样,复制/粘贴,调试和使用。如果您遇到代码问题,我将很乐意提供帮助。如果答案有帮助,请将其标记为已回答。 问候,

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-14
      • 2016-10-13
      • 1970-01-01
      • 1970-01-01
      • 2014-03-12
      • 1970-01-01
      • 2016-09-07
      • 2013-02-14
      相关资源
      最近更新 更多