سؤال

ولقد اثنين من HeaderedContentControls مثل تلك أدناه أن يكون لكل خاصية المحتوى مكبلة إلى واحد من اثنين عرض خصائص نموذج من نفس النوع الأساسي (واحد السيطرة على الجانب الأيسر من النافذة واحد على اليمين، وبالتالي فإن نموذج عرض أسماء الملكية).

ولكن، إما بالنظر الملكية النموذج يمكن أن يكون واحدا من أربعة أنواع مختلفة مشتقة. حتى اليسار يمكن أن يكون Airplane والحق يمكن أن يكون Car. ثم في وقت لاحق، واليسار يمكن أن يكون Boat والحق يمكن أن يكون Airplane. أود الممتلكات Style من رأس تسيطر أن تكون ديناميكية على أساس نوع المشتقة. ما هي أفضل طريقة للقيام بذلك إلزامي؟

<Window...>
    <StackPanel 
        Grid.Row="2"
        Orientation="Horizontal" VerticalAlignment="Top">
        <Border 
            Height="380" 
            Width="330"
            Margin="0,0,4,0"
            Style="{StaticResource MainBorderStyle}">
            <HeaderedContentControl
                Content="{Binding Path=LeftChild}"
                Header="{Binding LeftChild.DisplayName}"
                Style="{StaticResource StandardHeaderStyle}"
            />
        </Border>

        <Border 
            Height="380" 
            Width="330"
            Style="{StaticResource MainBorderStyle}">
            <HeaderedContentControl
                Content="{Binding Path=RightChild}"
                Header="{Binding RightChild.DisplayName}"
                Style="{StaticResource StandardHeaderStyle}"
            />  
        </Border>
    </StackPanel>
</Window>


<ResourceDictionary 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:vm="clr-namespace:myViewModelNamespace;assembly=myViewModelAssembly"
    xmlns:vw="clr-namespace:myViewNamespace" >

    <!--***** Item Data Templates ****-->
    <DataTemplate DataType="{x:Type vm:CarViewModel}">
        <vw:CarView />
    </DataTemplate>

    <DataTemplate DataType="{x:Type vm:BoatViewModel}">
        <vw:BoatView />
    </DataTemplate>

    <DataTemplate DataType="{x:Type vm:AirplaneViewModel}">
        <vw:AirplaneView />
    </DataTemplate>

    <!--***** 
        Other stuff including the StandardHeaderStyle and the MainBorderStyle
    ****-->

</ResourceDictionary>
هل كانت مفيدة؟

المحلول

وجوابي هو وضع على لARCHIMED. لا تتردد في طرح المزيد!

<Window x:Class="Datatemplate_selector.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300"
xmlns:local="clr-namespace:Datatemplate_selector">
<Window.Resources>
    <DataTemplate DataType="{x:Type local:CarDetail}">
     <Border BorderBrush="Yellow" BorderThickness="2">
        <HeaderedContentControl Margin="4" Foreground="Red">
            <HeaderedContentControl.Header>
                <Border BorderBrush="Aquamarine" BorderThickness="3">
                    <TextBlock Text="{Binding Name}"/>
                </Border>
             </HeaderedContentControl.Header>
            <HeaderedContentControl.Content>
                <Border BorderBrush="CadetBlue" BorderThickness="1">
                    <TextBlock TextWrapping="Wrap" Text="{Binding Description}"/>
                </Border>
            </HeaderedContentControl.Content>
        </HeaderedContentControl>
       </Border>
    </DataTemplate>
    <DataTemplate DataType="{x:Type local:HouseDetail}">
        <HeaderedContentControl Margin="4" Foreground="Yellow" FontSize="20"
                    Header="{Binding Name}">
            <HeaderedContentControl.Content>
                <TextBlock Foreground="BurlyWood"  TextWrapping="Wrap"
                           Text="{Binding Description}"/>
            </HeaderedContentControl.Content>
        </HeaderedContentControl>
    </DataTemplate>
    <DataTemplate DataType="{x:Type local:ItemDetail}">
        <HeaderedContentControl Margin="4" Foreground="Green" FontStyle="Italic" 
                    Content="{Binding Description}"
                    Header="{Binding Name}">
        </HeaderedContentControl>
    </DataTemplate>
</Window.Resources>
<StackPanel>
    <ItemsControl ItemsSource="{Binding ItemDetails}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <UniformGrid Columns="2"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>
</StackPanel>

using System.Collections.ObjectModel;
using System.Windows;

namespace Datatemplate_selector
{
   public partial class Window1 : Window
    {
        public ObservableCollection<ItemDetail> ItemDetails { get; set; }

        public Window1()
        {
            ItemDetails = new ObservableCollection<ItemDetail>
                              {
                                  new CarDetail{Name="Trabant"},
                                  new HouseDetail{Name="Taj Mahal"}
                              };
            DataContext = this;
            InitializeComponent();
        }
    }

    public class ItemDetail:DependencyObject
    {
        public string Name
        {
            get { return (string)GetValue(NameProperty); }
            set { SetValue(NameProperty, value); }
        }

        public static readonly DependencyProperty NameProperty =
            DependencyProperty.Register("Name",
            typeof(string),
            typeof(ItemDetail),
            new UIPropertyMetadata(string.Empty));

        public virtual string Description
        {
             get { return Name + " has a lot of details"; }
        }
    }

    public class CarDetail:ItemDetail
    {
        public override string Description
        {
            get { return string.Format("The car {0} has two doors and a max speed of 90 kms/hr", Name); }
        }
    }

    public class HouseDetail:ItemDetail
    {
        public override string Description
        {
            get { return string.Format("The house {0} has two doors and a backyard", Name); }
        }
    }
}

وPS: أعتقد أن هذا الاستخدام من الميراث في جمع عام وغير معتمدة في صافي 3. أنا مندهش ممتع أن هذا الرمز يعمل

نصائح أخرى

هل أنت متأكد أنك بحاجة لتغيير نمط HeaderedContentControl، وليس ContentTemplate مستندة على نوع الديناميكي مشاركاتي؟ وبعبارة أخرى: هل تحتاج لتغيير أسلوب التحكم أو تحتاج فقط لتغيير بيانات قالب العنصر

ولأن هناك ContentTemplateSelector الملكية مفيد جدا، وإذا كنت سوف أكتب فئة بسيطة جدا عليك أن تكون قادرا على تحديد DataTemplate مستندة على نوع الديناميكي المحتوى.

وإذا كان هذا ليس هو الحال وأنت متأكد من أنك تحتاج لتغيير نمط، ثم هل يمكن أن يرجى وضع القليل الذي أجزاء من النمط الذي ترغب في تغيير - ربما الحل من خلال نفس ContentTemplateSelector هناك متاح <. / P>

في حالة الإصرار على اختلاف الأساليب، والتفكير قليلا حول استخدام الزناد البيانات داخل طريقتك - استخدام محول بسيط جدا عليك أن تكون قادرا على تغيير خصائص معينة (أو لهم جميعا إذا كنت تفضل ذلك) من نمط حياتك.

وسوف نكون سعداء لتوفر لك المزيد من المساعدة في أقرب وقت كما عليك وضع تفاصيل مشكلتك.

على UPD : لOK، يصر البلاغ أنه بحاجة لتغيير نمط. وهنا اثنين من الطرق الممكنة لكيف يمكنك أن تفعل ذلك.

أولا والحل بسيط، ولكن محدودة للغاية واحدة: منذ محتوى Header الخاص بك يمكن أن تكون محددة من خلال محتوى Content يمكنك القيام بذلك:

<DataTemplate x:Key="DefaultTemplate">
    <HeaderedContentControl Content="{Binding}"
                            Header="{Binding DisplayName}"
                            Style="{StaticResource DefaultStyle}" />
</DataTemplate>
<DataTemplate x:Key="CarTemplate"
              DataType="dm:Car">
    <HeaderedContentControl Content="{Binding}"
                            Header="{Binding DisplayName}"
                            Style="{StaticResource CarStyle}" />
</DataTemplate>
<DataTemplate x:Key="BoatTemplate"
              DataType="dm:Boat">
    <HeaderedContentControl Content="{Binding}"
                            Header="{Binding DisplayName}"
                            Style="{StaticResource BoatStyle}" />
</DataTemplate>

<u:TypeBasedDataTemplateSelector x:Key="MySelector"
                                 DefaultTemplate="{StaticResource DefaultTemplate}"
                                 NullTemplate="{StaticResource DefaultTemplate}">
    <u:TypeMapping Type="dm:Car" Template="{StaticResource CarTemplate}" />
    <u:TypeMapping Type="dm:Boat" Template="{StaticResource BoatTemplate}" />
</u:TypeBasedDataTemplateSelector>

<ContentPresenter Content="{Binding LeftChild}"
                  ContentTemplateSelector="{StaticResource MySelector}" />

والرمز الوحيد الذي سوف تحتاج إلى دعم هذا الحل التعريفي بحتة هو تطبيق بسيط جدا قالب محدد. هنا غني:

public class TypeMapping
{
    public Type Type { get; set; }
    public DataTemplate Template { get; set; }
}

public class TypeBasedDataTemplateSelector : DataTemplateSelector, IAddChild
{
    public DataTemplate DefaultTemplate { get; set; }
    public DataTemplate NullTemplate { get; set; }
    private readonly Dictionary<Type, DataTemplate> Mapping = new Dictionary<Type, DataTemplate>();

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        if (item == null)
            return NullTemplate;

        DataTemplate template;

        if (!Mapping.TryGetValue(item.GetType(), out template))
            template = DefaultTemplate;

        return template;
    }


    #region IAddChild Members

    public void AddChild(object value)
    {
        if (!(value is TypeMapping))
            throw new Exception("...");

        var tm = (TypeMapping)value;

        Mapping.Add(tm.Type, tm.Template);
    }

    public void AddText(string text)
    {
        throw new NotImplementedException();
    }

    #endregion
}

والحل الثاني هو أكثر عمومية، ويمكن تطبيقها على الحالات التي يكون فيها محتوى Header له علاقة مع المحتوى Content شيء. وهي تبني على ربط لقدرات المحول.

<Style x:Key="StandardHeaderedStyle">
    <!--...-->
</Style>

<Style x:Key="CarHeaderedStyle"
       BasedOn="{StaticResource StandardHeaderedStyle}">
    <!--...-->
</Style>

<Style x:Key="BoatHeaderedStyle"
       BasedOn="{StaticResource StandardHeaderedStyle}">
    <!--...-->
</Style>

<Style x:Key="UnknownHeaderedStyle"
       BasedOn="{StaticResource StandardHeaderedStyle}">
    <!--...-->
</Style>

<u:StylesMap x:Key="MyStylesMap" 
             FallbackStyle="{StaticResource UnknownHeaderedStyle}">
    <u:StyleMapping Type="Car" Style="{StaticResource CarHeaderedStyle}" />
    <u:StyleMapping Type="Boat" Style="{StaticResource BoatHeaderedStyle}" />
</u:StylesMap>

<u:StyleSelectorConverter x:Key="StyleSelectorConverter" />

<HeaderedContentControl Content="{Binding LeftChild}"
                        Header="{Binding LeftChild.DisplayName}">
    <HeaderedContentControl.Style>
        <Binding Path="LeftChild"
                 Converter="{StaticResource StyleSelectorConverter}"
                 ConverterParameter="{StaticResource MyStylesMap}" />
    </HeaderedContentControl.Style>
</HeaderedContentControl>

وهذا يتطلب أيضا بعض من التعليمات البرمجية دعم:

public class StyleMapping
{
    public Type Type { get; set; }
    public Style Style { get; set; }
}

public class StylesMap : Dictionary<Type, Style>, IAddChild
{
    public Style FallbackStyle { get; set; }

    #region IAddChild Members

    public void AddChild(object value)
    {
        if (!(value is StyleMapping))
            throw new InvalidOperationException("...");

        var m = (StyleMapping)value;

        this.Add(m.Type, m.Style);
    }

    public void AddText(string text)
    {
        throw new NotImplementedException();
    }

    #endregion
}

public class StyleSelectorConverter : IValueConverter
{
    #region IValueConverter Members

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var m = (StylesMap)parameter;

        if (value == null)
            return m.FallbackStyle;

        Style style;
        if (!m.TryGetValue(value.GetType(), out style))
            style = m.FallbackStyle;

        return style;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    #endregion
}

وHTH

ومحاولة استخدام فئة نمط محدد:

http://msdn.microsoft.com /en-us/library/system.windows.controls.styleselector.aspx

وأنا لم تستخدم بنفسي على وجه التحديد، لذلك ليس لدي أي رمز عينة لك للتحقق، ولكن الرابط MSDN لديه بعض.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top