Hallo auch,
heute mal ein paar Fragen von mir. Vorab: Ich bin kein Freund von WPF. Kann mit MVVM nix anfangen. Und liebe den WinForm-Designer, weil ich mit ihm (bzw. seinem mir seit VB 2.0 bekannten Vorgänger) die letzten 20 Jahre groß geworden bin. Nichtsdestotrotz bin ich nun "gezwungen", mich mit WPF auseinanderzusetzen.
Erste Ergebnisse meiner "Studien" resultierten in einem WPF Window mit einem darin enthaltenen Bereich, der nun geschickterweise zur Wiederverwendung in weiteren, späteren Anwendungen, in ein WPF-Control ausgelagert werden soll - wobei ein Großteil versiegelt werden soll (d.h. vom Control-Client nicht änderbar) und bestimmte andere Elemente in Form von Control-Eigenschaften steuerbar werden sollen.
Sinnvollerweise liegt die XAML-Definition dessen, was durch das Control repräsentiert werden soll, und dazu zählen auch die ControlTemplates der innerhalb dieses DockPanels verwendeten Elemente - auch alles brav in einem einzigen XML-Element, in diesem Fall einem DockPanel.
Ausschnitt des für das Control relevanten XAMLs
Anmerkungen dazu
Der geübte Betrachter wird recht schnell bemerken: In diesem XAML gibt es drei Stellen, wo das Control später seinen "Content" aufnehmen soll, bzw. wo es vom Benutzer des Controls mit Leben gefüllt werden soll. Ich habe sie mit entsprechenden Kommentaren markiert und mit "Main Toolbar", "TabMenu" und "Buttons Tab x" genannt.
Als erstes stellt sich mir die Frage: Ist nun ein "UserControl" oder ein "Userdefined Control" das richtige? Ich wage hier mal eine eigene Antwort und behaupte, ein "Userdefined Control" wäre doch der bessere (oder einzig sinnvolle) Ansatz.
Dann ist aber die Frage: Wie gehe ich ab hier am besten vor? Wie krieg ich jetzt aus dem XAML ein Control gebaut, dabei ggf. noch diverse Eigenschaften so "exportiert", dass der Benutzer des Controls hier Einfluß nehmen oder gar das Template modifizieren kann. Ein paar kleine Schubser, die mir für den Start die richtige Richtung weisen, dürften hoffentlich ausreichend sein.
Ach und dann noch abschließend, da ich jetzt den XAML-Code schonmal hier habe, eine Frage: Ich habe ja versucht, die Tab-Register mit einem eigenen Style zu versehen. Ich habe dazu PathGeometry-Elemente gebraucht, um den gewünschten Look zu erreichen. Dummerweise - wie auch das entsprechende Tutorial in diesem Forum bestätigte - greift bei Grafik-Pfaden die Eigenschaft "UseLayoutRounding" nicht, was leider dazu führt - obwohl ich nicht wirklich eine Erklärung dafür habe - dass manche der durch die Paths entstehenden Linien "zwischen" den Units liegen und somit verwischen. Hat jemand einen Vorschlag wie man das anders lösen kann, damit dieser Effekt nicht auftritt?
heute mal ein paar Fragen von mir. Vorab: Ich bin kein Freund von WPF. Kann mit MVVM nix anfangen. Und liebe den WinForm-Designer, weil ich mit ihm (bzw. seinem mir seit VB 2.0 bekannten Vorgänger) die letzten 20 Jahre groß geworden bin. Nichtsdestotrotz bin ich nun "gezwungen", mich mit WPF auseinanderzusetzen.
Erste Ergebnisse meiner "Studien" resultierten in einem WPF Window mit einem darin enthaltenen Bereich, der nun geschickterweise zur Wiederverwendung in weiteren, späteren Anwendungen, in ein WPF-Control ausgelagert werden soll - wobei ein Großteil versiegelt werden soll (d.h. vom Control-Client nicht änderbar) und bestimmte andere Elemente in Form von Control-Eigenschaften steuerbar werden sollen.
Sinnvollerweise liegt die XAML-Definition dessen, was durch das Control repräsentiert werden soll, und dazu zählen auch die ControlTemplates der innerhalb dieses DockPanels verwendeten Elemente - auch alles brav in einem einzigen XML-Element, in diesem Fall einem DockPanel.
Quellcode
- <DockPanel SnapsToDevicePixels="True" UseLayoutRounding="True" DockPanel.Dock="Top" LastChildFill="True">
- <Border BorderThickness="0,1" BorderBrush="{x:Static SystemColors.ControlDarkDarkBrush}">
- <DockPanel Name="ToolbarControl" DockPanel.Dock="Top" LastChildFill="True">
- <DockPanel.Background>
- <LinearGradientBrush EndPoint="0,1">
- <GradientStop Color="White" Offset="0" />
- <GradientStop Color="{x:Static SystemColors.ControlDarkColor}" Offset="1" />
- </LinearGradientBrush>
- </DockPanel.Background>
- <Image Name="HeaderImage" Source="/WpfApplication1;component/Images/leftheader.gif" DockPanel.Dock="Left" Visibility="Visible" ClipToBounds="False" Height="{Binding ElementName=ToolbarPanel, Path=ActualHeight}"/>
- <StackPanel Name="ToolbarPanel" DockPanel.Dock="Top" VerticalAlignment="Top" Margin="0" Focusable="False" Orientation="Vertical">
- <StackPanel.Resources>
- <Style TargetType="TabItem">
- <Setter Property="Template">
- <Setter.Value>
- <ControlTemplate TargetType="TabItem">
- <ControlTemplate.Resources>
- <PathGeometry x:Key="TabBottomLine">
- <PathFigure StartPoint="-5,20" IsClosed="False" IsFilled="False">
- <PathFigure.Segments>
- <LineSegment Point="5000,20"/>
- </PathFigure.Segments>
- </PathFigure>
- </PathGeometry>
- <PathGeometry x:Key="TabGeometryInactive">
- <PathFigure StartPoint="0,20" IsClosed="False" IsFilled="True">
- <PathFigure.Segments>
- <!--<LineSegment Point="0,20"/>-->
- <LineSegment Point="0,5"/>
- <ArcSegment IsSmoothJoin="True" Point="5,0" RotationAngle="45" SweepDirection="Clockwise" Size="5,5" />
- <LineSegment IsSmoothJoin="True" Point="70,0" />
- <ArcSegment IsSmoothJoin="True" Point="75,5" Size="5,5" SweepDirection="Clockwise" />
- <LineSegment IsSmoothJoin="True" Point="75,20" />
- </PathFigure.Segments>
- </PathFigure>
- <PathFigure StartPoint="-5,20" IsClosed="False" IsFilled="False">
- <LineSegment Point="80,20"/>
- </PathFigure>
- </PathGeometry>
- <PathGeometry x:Key="TabGeometryActive">
- <PathFigure StartPoint="-5,20" IsClosed="False" IsFilled="False">
- <PathFigure.Segments>
- <LineSegment Point="0,20"/>
- </PathFigure.Segments>
- </PathFigure>
- <PathFigure StartPoint="0,23" IsClosed="False" IsFilled="True">
- <PathFigure.Segments>
- <LineSegment Point="0,5"/>
- <ArcSegment IsSmoothJoin="True" Point="5,0" RotationAngle="45" SweepDirection="Clockwise" Size="5,5" />
- <LineSegment IsSmoothJoin="True" Point="70,0" />
- <ArcSegment IsSmoothJoin="True" Point="75,5" Size="5,5" SweepDirection="Clockwise" />
- <LineSegment IsSmoothJoin="True" Point="75,23" />
- </PathFigure.Segments>
- </PathFigure>
- </PathGeometry>
- </ControlTemplate.Resources>
- <Grid Margin="5 5 0 0" Width="76" Height="20">
- <Canvas Width="76" Height="20">
- <Path Data="{StaticResource TabBottomLine}" Visibility="Hidden" SnapsToDevicePixels="True" Name="TabBottomLine" Stroke="Black" StrokeThickness="1" />
- <Path Data="{StaticResource TabGeometryActive}" Visibility="Hidden" SnapsToDevicePixels="True" Name="ActiveTab" Stroke="Black" StrokeThickness="1">
- <Path.Fill>
- <LinearGradientBrush EndPoint="0,1">
- <GradientStop Color="White" Offset=".5"/>
- <GradientStop Color="Transparent" Offset="1"/>
- </LinearGradientBrush>
- </Path.Fill>
- </Path>
- <Path Data="{StaticResource TabGeometryInactive}" SnapsToDevicePixels="True" Name="InactiveTab" Stroke="Black" StrokeThickness="1" >
- <Path.Fill>
- <LinearGradientBrush EndPoint="0,1">
- <GradientStop Color="White" Offset="0"/>
- <GradientStop Color="Transparent" Offset="1"/>
- </LinearGradientBrush>
- </Path.Fill>
- </Path>
- <Path Clip="{StaticResource TabGeometryInactive}" Visibility="Hidden" Name="ActiveIndicator" Stroke="Orange" StrokeThickness="3" SnapsToDevicePixels="True">
- <Path.Data>
- <LineGeometry StartPoint="1,2" EndPoint="74,2"/>
- </Path.Data>
- </Path>
- </Canvas>
- <ContentPresenter x:Name="ContentSite" ContentSource="Header" Margin="0 2 0 0" HorizontalAlignment="Center" ClipToBounds="True" />
- </Grid>
- <ControlTemplate.Triggers>
- <Trigger Property="IsSelected" Value="True">
- <Setter Property="Panel.ZIndex" Value="100" />
- <Setter Property="FontWeight" Value="Bold"/>
- <Setter TargetName="ActiveIndicator" Property="Visibility" Value="Visible" />
- <Setter TargetName="InactiveTab" Property="Visibility" Value="Hidden" />
- <Setter TargetName="ActiveTab" Property="Visibility" Value="Visible" />
- </Trigger>
- <Trigger Property="IsEnabled" Value="False">
- <Setter TargetName="InactiveTab" Property="Fill" Value="LightGray" />
- <Setter Property="Foreground" Value="White" />
- <Setter TargetName="InactiveTab" Property="Visibility" Value="Visible" />
- <Setter TargetName="ActiveTab" Property="Visibility" Value="Hidden" />
- </Trigger>
- <Trigger Property="Header" Value="@">
- <Setter TargetName="ContentSite" Property="Visibility" Value="Hidden" />
- <Setter TargetName="TabBottomLine" Property="Visibility" Value="Visible" />
- <Setter TargetName="InactiveTab" Property="Visibility" Value="Hidden" />
- <Setter TargetName="ActiveTab" Property="Visibility" Value="Hidden" />
- </Trigger>
- </ControlTemplate.Triggers>
- </ControlTemplate>
- </Setter.Value>
- </Setter>
- </Style>
- <Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Static ToolBar.ButtonStyleKey}}">
- <Setter Property="Width" Value="38" />
- <Setter Property="Height" Value="38" />
- <Setter Property="BorderThickness" Value="1" />
- <Setter Property="Padding" Value="2" />
- <Setter Property="Focusable" Value="False"/>
- <Setter Property="IsTabStop" Value="False"/>
- <Setter Property="Command" Value="{x:Static my:MyCommands.ToolbarButton}"/>
- </Style>
- <Style TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource {x:Static ToolBar.ToggleButtonStyleKey}}">
- <Setter Property="Width" Value="38" />
- <Setter Property="Height" Value="38" />
- <Setter Property="BorderThickness" Value="1" />
- <Setter Property="Padding" Value="2" />
- <Setter Property="Focusable" Value="False"/>
- <Setter Property="IsTabStop" Value="False"/>
- <Setter Property="Command" Value="{x:Static my:MyCommands.ToolbarButton}"/>
- </Style>
- <Style TargetType="{x:Type CheckBox}" BasedOn="{StaticResource {x:Type ToggleButton}}"/>
- <Style TargetType="{x:Type RadioButton}" BasedOn="{StaticResource {x:Static ToolBar.RadioButtonStyleKey}}">
- <Setter Property="Width" Value="38" />
- <Setter Property="Height" Value="38" />
- <Setter Property="BorderThickness" Value="1" />
- <Setter Property="Padding" Value="2" />
- <Setter Property="Focusable" Value="False"/>
- <Setter Property="IsTabStop" Value="False"/>
- <Setter Property="Command" Value="{x:Static my:MyCommands.ToolbarButton}"/>
- </Style>
- <Style TargetType="{x:Type Image}">
- <Setter Property="Height" Value="{x:Static SystemParameters.IconHeight}"/>
- </Style>
- </StackPanel.Resources>
- <Border BorderThickness="0,0,0,1" BorderBrush="{x:Static SystemColors.ControlDarkDarkBrush}">
- <DockPanel>
- <Image Name="Logo" Height="30" DockPanel.Dock="Right" Margin="0 0 5 0" VerticalAlignment="Center" Source="/WpfApplication1;component/Images/38.png"/>
- <StackPanel Margin="0 1" Height="38" Name="MainToolbar" Orientation="Horizontal">
- <!--########################### Main Toolbar ################################## //-->
- <Button Command="{x:Static my:MyCommands.Exit2}">
- <Image Source="/WpfApplication1;component/Images/icon1.ico" />
- </Button>
- <Button Content="Open" Command="Open"/>
- <Button Content="OK"/>
- <Button>TEST</Button>
- <Button Content="Add" CommandParameter="AddPart" ToolTip="Dies ist ein Tooltip"/>
- <Button>_Hilfe</Button>
- <Separator/>
- <ToggleButton>Check</ToggleButton>
- <CheckBox>Hallo</CheckBox>
- <Separator/>
- <Button Content="K1"/>
- <Button Content="Exit" Command="{x:Static my:MyCommands.Exit2}"/>
- <!--########################### Main Toolbar Ende ############################# //-->
- </StackPanel>
- </DockPanel>
- </Border>
- <TabControl Background="Transparent" IsTabStop="False" Margin="0 2 0 0" Focusable="False" Name="tabControl1" MinHeight="25" Padding="2" BorderThickness="0">
- <!--########################### TabMenu ################################## //-->
- <TabItem Header="Tab 1">
- <StackPanel Orientation="Horizontal">
- <!--###### Buttons Tab 1 ###### //-->
- <Button Name="btnToAdorn">K1</Button>
- <Button>K2</Button>
- <Button>K3</Button>
- <Button>K4</Button>
- <Button>K5</Button>
- </StackPanel>
- </TabItem>
- <TabItem Header="Tab 2">
- <StackPanel Orientation="Horizontal">
- <!--###### Buttons Tab 2 ###### //-->
- <Button>A1</Button>
- </StackPanel>
- </TabItem>
- <TabItem Header="Tab 3">
- <StackPanel Orientation="Horizontal">
- <!--###### Buttons Tab 3 ###### //-->
- <Button Content="K1"/>
- </StackPanel>
- </TabItem>
- <TabItem Header="Tab 4" IsEnabled="False">
- <StackPanel Orientation="Horizontal">
- <!--###### Buttons Tab 4 ###### //-->
- <Button>N1</Button>
- <Button>N1</Button>
- <Button>N1</Button>
- <Button>N1</Button>
- </StackPanel>
- </TabItem>
- <!--########################### TabMenu Ende ############################# //-->
- <TabItem Header="@" IsEnabled="False" />
- </TabControl>
- </StackPanel>
- </DockPanel>
- </Border>
- </DockPanel>
Ja, ich weiß, dass manche Buttons "seltsame" Bezeichnungen haben bzw. einige der enthaltenen Elemente an keinen Befehl gebunden sind. Das ist so "gewollt" bzw. dient nur zu Testzwecken.
Das letzte TabItem mit dem Header "@" soll fest sein und wurde von mir dafür "missbraucht", um neben den normalen TabItems noch eine durchgehende Linie hinzubekommen, ohne die das Gesamtbild sch***e aussehen würde. Vllt. gibts ja ne bessere Idee, wie ich diese Linie so gestalten kann, dass das Gesamtbild am Ende das gleiche ist.
Das letzte TabItem mit dem Header "@" soll fest sein und wurde von mir dafür "missbraucht", um neben den normalen TabItems noch eine durchgehende Linie hinzubekommen, ohne die das Gesamtbild sch***e aussehen würde. Vllt. gibts ja ne bessere Idee, wie ich diese Linie so gestalten kann, dass das Gesamtbild am Ende das gleiche ist.
Der geübte Betrachter wird recht schnell bemerken: In diesem XAML gibt es drei Stellen, wo das Control später seinen "Content" aufnehmen soll, bzw. wo es vom Benutzer des Controls mit Leben gefüllt werden soll. Ich habe sie mit entsprechenden Kommentaren markiert und mit "Main Toolbar", "TabMenu" und "Buttons Tab x" genannt.
Als erstes stellt sich mir die Frage: Ist nun ein "UserControl" oder ein "Userdefined Control" das richtige? Ich wage hier mal eine eigene Antwort und behaupte, ein "Userdefined Control" wäre doch der bessere (oder einzig sinnvolle) Ansatz.
Dann ist aber die Frage: Wie gehe ich ab hier am besten vor? Wie krieg ich jetzt aus dem XAML ein Control gebaut, dabei ggf. noch diverse Eigenschaften so "exportiert", dass der Benutzer des Controls hier Einfluß nehmen oder gar das Template modifizieren kann. Ein paar kleine Schubser, die mir für den Start die richtige Richtung weisen, dürften hoffentlich ausreichend sein.
Ach und dann noch abschließend, da ich jetzt den XAML-Code schonmal hier habe, eine Frage: Ich habe ja versucht, die Tab-Register mit einem eigenen Style zu versehen. Ich habe dazu PathGeometry-Elemente gebraucht, um den gewünschten Look zu erreichen. Dummerweise - wie auch das entsprechende Tutorial in diesem Forum bestätigte - greift bei Grafik-Pfaden die Eigenschaft "UseLayoutRounding" nicht, was leider dazu führt - obwohl ich nicht wirklich eine Erklärung dafür habe - dass manche der durch die Paths entstehenden Linien "zwischen" den Units liegen und somit verwischen. Hat jemand einen Vorschlag wie man das anders lösen kann, damit dieser Effekt nicht auftritt?
Weltherrschaft erlangen: 1%
Ist dein Problem erledigt? -> Dann markiere das Thema bitte entsprechend.
Waren Beiträge dieser Diskussion dabei hilfreich? -> Dann klick dort jeweils auf den Hilfreich-Button.
Danke.
Waren Beiträge dieser Diskussion dabei hilfreich? -> Dann klick dort jeweils auf den Hilfreich-Button.
Danke.