/ / Dynamische Anzeige eines Steuerelements in Abhängigkeit von der gebundenen Eigenschaft mit WPF - .net, wpf

Dynamisches Anzeigen eines Steuerelements in Abhängigkeit von der gebundenen Eigenschaft mithilfe von WPF - .net, wpf

Ich habe eine Eigenschaft mit einem Datenbankdatentyp (char, datetime, int, float usw.) und möchte das Steuerelement ändern, mit dem ein Wert des ausgewählten Typs eingegeben wird TextBox und für Datumswerte möchte ich a DatePicker.

Eine Möglichkeit, über die ich nachdachte, bestand darin, jedes Steuerelement in meinem Formular zu haben und das entsprechende festzulegen Visibility mit einem geeigneten IValueConverter Implementierung. Ich weiß, dass dies funktionieren wird, aber es würde viel Code erzeugen und fühlt sich nicht sehr gut an.

Der andere Weg, den ich dachte, war, a zu benutzen ContentPresenter und setze seinen Inhalt mit a Style und DataTriggers aber ich kann es nicht zum Laufen bringen.

    <Style x:Key="TypedValueHelper" TargetType="{x:Type ContentPresenter}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=DataType}" Value="Char">
<Setter Property="Content" Value="???"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=DataType}" Value="Date">
<Setter Property="Content" Value="???"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=DataType}" Value="Integer">
<Setter Property="Content" Value="???"/>
</DataTrigger>
</Style.Triggers>
</Style>

Wenn jemand mein "???" Oder bieten Sie eine bessere Lösung an.

Antworten:

10 für die Antwort № 1

Sie könnten eine Kombination von Stil mit Setzern machenund Datenvorlagen. Sie haben im Grunde den Anfang dafür in Ihrem Code, obwohl ich nicht denke, dass ContentPresenter das richtige Steuerelement zum Gestalten ist, da es keine Vorlage hat.

Möglich so etwas:

<Style x:Key="TypedValueHelper" TargetType="{x:Type ContentControl}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=DataType}" Value="Char">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBox Text="{Binding Path=.}" />
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Path=DataType}" Value="Integer">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Slider Maximum="100" Minimum="0" Value="{Binding Path=.}"
Orientation="Horizontal" />
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>

...

<ContentControl Content="{Binding MyValue}"
Style="{StaticResource TypedValueHelper}">

5 für die Antwort № 2

Während die Style-Lösung möglicherweise funktioniert, ist die richtigeEine Möglichkeit, das dynamische Inhaltsverhalten zu implementieren, besteht darin, DataTemplates wie von Sdry vorgeschlagen zu verwenden. Sie würden jedoch eine Aufzählung verwenden, um zu bestimmen, welches DataTemplate verwendet werden soll. Dies bedeutet im Wesentlichen, dass Sie einen einzelnen Typ mehreren DataTemplates zuordnen möchten. Dieses Problem wird durch die DataTemplateSelector-Klasse gelöst. Die folgende Beschreibung stammt direkt von MSDN:


"In der Regel erstellen Sie einen DataTemplateSelectorwenn Sie mehr als eine DataTemplate für denselben Objekttyp haben und Ihre eigene Logik bereitstellen möchten, um eine DataTemplate auszuwählen, die basierend auf den Eigenschaften jedes Datenobjekts angewendet werden soll. "


Ihr dynamischer Inhalt sollte von einem ContentControl wie folgt gehostet werden:

   <ContentControl Content="{Binding Path=ReferenceToYourViewModel}" ContentTemplateSelector="{DynamicResource MyTemplateSelector}"/>

Die Implementierung von MyTemplateSelector:

    public class MyTemplateSelector: DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
FrameworkElement elem = container as FrameworkElement;
if(elem == null)
{
return null;
}
if (item == null || !(item is YourViewModel))
{
throw new ApplicationException();
}
if ((item as YourViewModel).DataType == DataType.Char)
{
return elem.FindResource("CharDataTemplate") as DataTemplate;
}
if ((item as YourViewModel).DataType == DataType.Date)
{
return elem.FindResource("DateDataTemplate") as DataTemplate;
}
if ((item as YourViewModel).DataType == DataType.Integer)
{
return elem.FindResource("IntegerDataTemplate") as DataTemplate;
}
throw new ApplicationException();
}
}

Dann, wie Sie es erwarten würden, sind hier die DataTemplates, aus denen Sie auswählen können:

   <DataTemplate x:Key="CharDataTemplate" DataType="{x:Type YourViewModel}">Put Your Xaml Here</DataTemplate>
<DataTemplate x:Key="DateDataTemplate" DataType="{x:Type YourViewModel}">Put Your Xaml Here</DataTemplate>
<DataTemplate x:Key="IntegerDataTemplate" DataType="{x:Type YourViewModel}">Put Your Xaml Here</DataTemplate>

Mit dieser Option wird das entsprechende DataTemplate basierend auf der DataType-Eigenschaft Ihres View-Modells ausgewählt. Was meiner Meinung nach viel sauberer ist als die Verwendung von Visibility oder Styles.


0 für die Antwort № 3

Ich würde in DataTemplates suchen. Zum Beispiel:

<DataTemplate DataType="{x:Type local:Input}">
<local:InputControl DataContext="{Binding}" />
</DataTemplate>

<DataTemplate DataType="{x:Type data:VideoData}">
<local:VideoControl DataContext="{Binding}"></local:VideoControl>
</DataTemplate>