Frage

Ich bin versucht, erstellen Sie eine benutzerdefinierte Steuerung - eine Taste, die mehrere Stile angewendet, um es, je nach dem Wert einer Immobilie innerhalb der Daten-Rahmen.

Was ich dachte ist, mit so etwas wie:

<Button Style="{Binding Path=ButtonStyleProperty, Converter={StaticResource styleConverter}}" Text="{Binding Path=TextProp}" />

Und im code...Implementieren Sie einen IValueConverter, die etwas ähnliches macht, um den code unten in die ConvertTo Methode:

switch(value as ValueEnums)
{
    case ValueEnums.Enum1:
        FindResource("Enum1ButtonStyle") as Style;
    break;

    ... and so on.
} 

Aber ich bin mir nicht ganz sicher über, wie zu ziehen aus dem style-Objekt und selbst wenn dies überhaupt möglich ist...

Was mache ich in der Zwischenzeit ist die Behandlung der DataContextChanged Ereignis, dann anbringen, einen handler zu PropertyChanged Ereignis des Objekts gebunden wird, um die Taste - dann läuft die switch-Anweisung auf es.

Es ist nicht ganz perfekt, aber bis ich das finden einer besseren Lösung, wie es scheint,, dass ist, was ich haben werde, zu verwenden.

War es hilfreich?

Lösung

Wenn Sie wollen zu ersetzen die ganze Stil (anstatt nur Elemente davon), dann werden Sie wahrscheinlich speichern diese Stile an Ressourcen.Sie sollten in der Lage sein, etwas zu tun, entlang der Linien von:

<Button>
    <Button.Style>
        <MultiBinding Converter="{StaticResource StyleConverter}">
            <MultiBinding.Bindings>
                <Binding RelativeSource="{RelativeSource Self}"/>
                <Binding Path="MyStyleString"/>
            </MultiBinding.Bindings>
        </MultiBinding>
    </Button.Style>
</Button>

Durch die Verwendung einer MultiBinding und verwenden von Self als erstes binden wir können dann lookup-Ressourcen-Konverter.Der Konverter muss IMultiValueConverter implementieren (anstatt IValueConverter) und können wie folgt Aussehen:

class StyleConverter : IMultiValueConverter 
{
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        FrameworkElement targetElement = values[0] as FrameworkElement; 
        string styleName = values[1] as string;

        if (styleName == null)
            return null;

        Style newStyle = (Style)targetElement.TryFindResource(styleName);

        if (newStyle == null)
            newStyle = (Style)targetElement.TryFindResource("MyDefaultStyleName");

        return newStyle;
    }

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

Es ist nicht etwas, was ich sehr Häufig, aber diese Arbeit sollte von Speicher :)

Andere Tipps

Es scheint, dass Sie Datatrigger verwenden müssen Klasse. Es ermöglicht Ihnen, verschiedene Stile auf Ihre Schaltfläche anwenden, basierend auf seinen Inhalt.

Zum Beispiel folgender Stil wird Schaltfläche Hintergrund Eigenschaft auf rot basierend auf dem Wert der Datenkontext-Eigenschaft des Objekts ändern

<Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
    <Style.Triggers>
        <DataTrigger Binding="{Binding Path="Some property"}" 
                     Value="some property value">
            <Setter Property="Background" Value="Red"/>
        </DataTrigger>
    </Style.Triggers>
</Style>

Für diejenigen von uns, die nicht verwenden können die multi-Wert-Konverter (ich freu mich auf Euch SL4 und WP7:), danke an Steven ' s Antwort habe ich einen Weg gefunden, mit einem normalen Wert-Konverter.

Die einzige Annahme ist die Art Wert enthalten ist, innerhalb der Eigenschaft des Stils gesetzt.

Wenn Sie das MVVM-Muster dann den Stil mit dem Wert (wie TextSmall, TextMedium, TextLarge) wird davon ausgegangen, dass ein Teil der view-Modell, und alles, was Sie tun müssen, ist pass-die Wandler-parameter definieren Sie den Namen des Stils.

Zum Beispiel, sagen Sie Ihr view-Modell hat die Eigenschaft:

public string ProjectNameStyle
{
    get { return string.Format("ProjectNameStyle{0}", _displaySize.ToString()); }
}

Anwendung Art:

<Application.Resources>
    <Style x:Key="ProjectNameStyleSmall" TargetType="TextBlock">
        <Setter Property="FontSize" Value="40" />
    </Style>
    <Style x:Key="ProjectNameStyleMedium" TargetType="TextBlock">
        <Setter Property="FontSize" Value="64" />
    </Style>
    <Style x:Key="ProjectNameStyleLarge" TargetType="TextBlock">
        <Setter Property="FontSize" Value="90" />
    </Style>

Der XAML-Ansicht:

   <TextBlock 
        Text="{Binding Name}"
        Style="{Binding ., Mode=OneWay, Converter={cv:StyleConverter}, ConverterParameter=ProjectNameStyle}">

Mit Ihrem StyleConverter Klasse die IValueConverter:

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
    if (targetType != typeof(Style))
    {
        throw new InvalidOperationException("The target must be a Style");
    }

    var styleProperty = parameter as string;
    if (value == null || styleProperty == null)
    {
        return null;
    }

    string styleValue = value.GetType()
        .GetProperty(styleProperty)
        .GetValue(value, null)
        .ToString();
    if (styleValue == null)
    {
        return null;
    }

    Style newStyle = (Style)Application.Current.TryFindResource(styleValue);
    return newStyle;
}

Beachten Sie, dass dies ist WPF-code, der Konverter ist abgeleitet von einem MarkupExtension sowie IValueConverter, aber es funktioniert in SL4 und WP7 wenn Sie statische Ressource und fügen Sie ein wenig mehr Beinarbeit als TryFindResource Methode nicht vorhanden.

Hoffe, das hilft jemandem, und nochmals vielen Dank Steven!

Ansichtsmodell

private Style _dynamicStyle = (Style)Application.Current.FindResource("Style1");
        public Style DynamicStyle
        {
            get { return _dynamicStyle; }
            set
            {
                _dynamicStyle = value;
                OnPropertyChanged("DynamicStyle");
            }

        }

public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

Implementieren Sie eine Eigenschaft in Ihrem Viewmodel und dann dynamisch Stil ändern, wo immer Sie wie unten wollen.

DynamicStyle=(Style)Application.Current.FindResource("Style2");// you can place this code where the action get fired

Dann setzen Sie Datacontext Wert und dann implementieren Sie den folgenden Code in der Ansicht

    <Button Style="{Binding DynamicStyle,Mode=TwoWay}"/>
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top