none
Custom Control - Variablen in anderen TargetTypes verwenden RRS feed

  • Frage

  • Ich habe in meinem Control ScrollTab die Eigenschaft CornerRad (CornerRadius) definiert, und möchte sie in nachfolgendem Beispiel auch bei anderen untergeordneten Steuerelementen verwenden (in diesem Fall ein Thumb). Da ich den TargetType ändere, kann ich auf diese Eigenschaft allerdings nicht mehr zugreifen,

    wie könnte ich die CornerRad Property für alle Sub-Elemente verwenden?

    Ich habe bereits an eine StaticResource gedacht, da ich diese anscheinend überall im Code ansprechen kann, doch habe ich keine Ahnung, wie ich das funktionstüchtig realisieren könnte ...

    Außerdem muss die Länge dieses Thumbs im Programmablauf später geändert werden. Ich programmiere in C#.

    Wie funktioniert "get & set" der Resources im ResourceDictionary des Generic.xaml inC#?

     

    Generic.xaml:

     

     

    <ResourceDictionary
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:PF"
        xmlns:system="clr-namespace:System;assembly=mscorlib"
        >
    
        <LinearGradientBrush x:Key="AverageButton" StartPoint="0.5,0" EndPoint="0.5,1">
            <GradientBrush.GradientStops>
                <GradientStopCollection>
                    <GradientStop Color="#FF555555" Offset="0.0" />
                    <GradientStop Color="#FF4c4c4c" Offset="1.0" />
                </GradientStopCollection>
            </GradientBrush.GradientStops>
        </LinearGradientBrush>
        <LinearGradientBrush x:Key="AverageButton_Pressed" StartPoint="0.5,0" EndPoint="0.5,1">
            <GradientBrush.GradientStops>
                <GradientStopCollection>
                    <GradientStop Color="#FF4c4c4c" Offset="0.0" />
                    <GradientStop Color="#FF555555" Offset="1.0" />
                </GradientStopCollection>
            </GradientBrush.GradientStops>
        </LinearGradientBrush>
        <LinearGradientBrush x:Key="AverageButton_Hover" StartPoint="0.5,0" EndPoint="0.5,1">
            <GradientBrush.GradientStops>
                <GradientStopCollection>
                    <GradientStop Color="#FF666666" Offset="0.0" />
                    <GradientStop Color="#FF5d5d5d" Offset="1.0" />
                </GradientStopCollection>
            </GradientBrush.GradientStops>
        </LinearGradientBrush>
        
        <Style TargetType="{x:Type local:ScrollTab}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type local:ScrollTab}">
                        <Grid Name="MainGrid">
                            <Border 
                                x:Name="MainBorder"
                                CornerRadius="{Binding CornerRad, RelativeSource={RelativeSource TemplatedParent}, UpdateSourceTrigger=PropertyChanged}"
                                Background="{TemplateBinding Background}"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}"
                                />
                            <Track Name="Main_Track" IsDirectionReversed="False">
                                <Track.Thumb>
                                    <Thumb MinWidth="50">
                                        <Thumb.Template>
                                            <ControlTemplate TargetType="{x:Type Thumb}">
                                                <Border Name="Border"
                                                    CornerRadius="10"
                                                    Background="{StaticResource AverageButton}"
                                                    BorderBrush="{TemplateBinding BorderBrush}"
                                                    BorderThickness="{TemplateBinding BorderThickness}"
                                                />
                                                <ControlTemplate.Triggers>
                                                    <Trigger Property="IsMouseOver" Value="true">
                                                        <Setter TargetName="Border" Property="Background" Value="{StaticResource AverageButton_Hover}" />
                                                    </Trigger>
                                                    <Trigger Property="IsDragging" Value="true" >
                                                        <Setter TargetName="Border" Property="Background" Value="{StaticResource AverageButton_Pressed}" />
                                                    </Trigger>
                                                </ControlTemplate.Triggers>
                                            </ControlTemplate>
                                        </Thumb.Template>
                                    </Thumb>
                                </Track.Thumb>
                            </Track>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ResourceDictionary>


     









    Montag, 7. November 2011 20:00

Antworten

  • Hi,

    Du kannst Dich mit

    {Binding Path=CornerRad, RelativeSource={RelativeSource AncestorType={x:Type x:Type local:ScrollTab}}}

    auf Elemente beziehen, die sich im VisualTree oberhalb des Ziel-Elements befinden. Das ist nicht die schnellste Art, die Binding-Quelle zu bestimmen und sollte demzufolge in Controls mit vielen zu stylenden Unterelementen (DataGrid, ListView, ...) mit Bedacht eingesetzt werden.

    Auf die übrigen Anmerkungen/Fragen kann ich Dir leider nicht antworten, da ich deren Zielsetzung nicht erkenne. Vielleich kannst Du das noch ein wenig präzisieren.

    Gruß
    Jürgen

    • Als Antwort markiert Phil T F Donnerstag, 10. November 2011 22:22
    Mittwoch, 9. November 2011 14:31

Alle Antworten

  • Hi,

    Du kannst Dich mit

    {Binding Path=CornerRad, RelativeSource={RelativeSource AncestorType={x:Type x:Type local:ScrollTab}}}

    auf Elemente beziehen, die sich im VisualTree oberhalb des Ziel-Elements befinden. Das ist nicht die schnellste Art, die Binding-Quelle zu bestimmen und sollte demzufolge in Controls mit vielen zu stylenden Unterelementen (DataGrid, ListView, ...) mit Bedacht eingesetzt werden.

    Auf die übrigen Anmerkungen/Fragen kann ich Dir leider nicht antworten, da ich deren Zielsetzung nicht erkenne. Vielleich kannst Du das noch ein wenig präzisieren.

    Gruß
    Jürgen

    • Als Antwort markiert Phil T F Donnerstag, 10. November 2011 22:22
    Mittwoch, 9. November 2011 14:31
  • Hallo Jürgen,

     

    Ich habe deinen Vorschlag ausprobiert und freue mich, dass der CornerRadius bei beiden Elementen geändert wird.

    Zu den Anmerkungen:

    Ich habe im oben stehenden Code einen Background über eine StaticResource gesetzt:

    Background={StaticResource AverageButton}

    DAS scheint überall zu funktionieren, daher dachte ich schon daran, meine benötigten Ressourcen genau wie "AverageButton" in Bereich "RessourceDictionary" du definieren und dann zu binden. Wäre das möglich, könnten die Performanceprobleme, die du erwähntest, umgangen werden .. (denke ich zumindest ..)

    Aber das war auch nur eine Idee, meine bisherigen Versuche sind gescheitert, diese Ressourcen zu binden.

     

     

    Zu der 2ten Frage:

    Nunja, den horizontalen Bereich, den man als Fläche des Controls wahrnimmt (Border) wird Elemente beinhalten, deren Länge je nach Anzahl der Elemente variiert; der Thumb soll ebenfalls genau diese Länge haben, da er über einem dieser Elemente positioniert werden soll.

    Daher müsste ich im C#Code nach dem Hinzufügen eines Elements die Größe des Thumbs ändern, welcher sich allerdings im Generic.xaml befindet und ich ihn bei meinen bisherigen Versuchen nicht direkt über den Namen ansprechen konnte. 

     

    --> Einerseits könnte ich eine Property für die Breite definieren und ein Binding auf diese erstellen, doch du hast mir ja bereits geraten, Abstand von übermäßigem Einsatz zu nehmen. 

    Besteht die Möglichkeit von GET & SET von Ressourcen / Ressourcenwerten im C# Code?

    (die Methode tryFindResource gibt es ja (GET), doch wie ändere ich die Ressource? Bekomme ich eine Referenz auf das Objekt zurück und kann das Objekt damit direkt ändern? Außerdem: Wird beim Ändern ein PropertyChanged - Event ausgelöst oder muss ich das selbst erledigen?)

    • Als Antwort markiert Phil T F Donnerstag, 10. November 2011 22:22
    • Tag als Antwort aufgehoben Phil T F Donnerstag, 10. November 2011 22:22
    Mittwoch, 9. November 2011 16:49
  • Hi,
    zusätzlich zu den StaticResources gibt es auch ... surprise, surprise ... DynamicResources, die geänderte Werte weitergeben. Wie das genau funktioniert, weiß ich nicht - hab ich bisher auch noch nie gebraucht.
    Ich würde Dir auch generell davon abraten, solche Konstrukte (Bindings über Ressourcen zu steuen) zu bauen, denn das kriegt in zwei Jahren keiner mehr auf die Reihe, was wann woher kommt. Bei meinem Hinweis auf die Performance habe ich an hunderte oder tausende Elemente gedacht (wenn sich jede Zelle eines DataGrids irgeneine Farbe o ä. beim Grid selbst abholt, dann wird der Aufbau wohl etwas länger dauern). Ich weiß ja nicht, was Du vorhast, aber 'ein paar Knöpfe' sind da sicher nicht kritisch.
    Dieses Nicht-Wissen (was Du vorhast) verhindert auch, dass ich Dir einen Rat für die Länge/Breite des Thumbs geben kann, aber das Layout-System der WPF ist so flexibel, dass ich mir nur schwer vorstellen kann, dass für eine Layout-Anpassung ein Binding nötig ist. Schau mal in den folgenden XAML-Code: Der rote Block folgt in seiner Breite dem Text, den Du in das Textfeld einbigst:
    <Grid>
       <Grid.ColumnDefinitions>
          <ColumnDefinition 
             Width="Auto" />
          <ColumnDefinition />
       </Grid.ColumnDefinitions>
       <Grid.RowDefinitions>
          <RowDefinition 
             Height="Auto" />
          <RowDefinition 
             Height="Auto" />
          <RowDefinition 
             Height="Auto" />
       </Grid.RowDefinitions>
       <TextBox 
          x:Name="TheBox" 
          Grid.ColumnSpan="2" 
          Margin="4" />
       <TextBlock 
          Grid.Column="0" 
          Grid.Row="1" 
          Margin="2" 
          MinWidth="20" 
          Text="{Binding Path=Text, ElementName=TheBox}" />
       <Border 
          Grid.Column="0" 
          Grid.Row="2" 
          Margin="2" 
          Background="Red" 
          Height="30" />
       <Border 
          Grid.Column="1" 
          Grid.Row="2" 
          Margin="2" 
          Background="Green" 
          Height="30" />
    </Grid>
    
    Wenn das also irgendwie in die Richtung geht, die Du beschreibst, wird sich das vielleicht auch ohne Ressourcen-Bindung erledigen lassen.
    Gruß
    Jürgen
    • Bearbeitet Jürgen Röhr Mittwoch, 9. November 2011 17:37 Layout des Textes war unbrauchbar
    Mittwoch, 9. November 2011 17:34