在DataTemplate中使用绑定数据

时间:2015-12-15 23:17:53

标签: wpf xaml mvvm data-binding datacontext

我有一个CustomWindow.cs,我使用DataTemplate进行装饰,因为有大量的内容变化。根据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中内容的双重定义不会起作用,但却无法想到替代方案。

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

1 个答案:

答案 0 :(得分:0)

首先欢迎来到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;
    }
}

这就是全部,复制/过去,调试和使用。如果你的代码有问题我会很乐意提供帮助。如果答案有帮助,请将其标记为已回答。 的问候,