none
WPF Steuerelement mit Dynamischer Größe RRS feed

  • Frage

  • Hallo,

    ich bin neu in der WPF und würde gerne ein set an Steuerelementen erstellen die ich dann auf meinem Form verwenden kann. nun kann mann ja mit der WPF PATHs anlegen und ich habe mir ein Steuerelement gemacht das aus ein paar PATHs besteht.

    Layout:

    <Grid x:Name="LayoutRoot">
    <Path Fill="#FF939497" Margin="0,12.001,0,0" Data="M85,6.964 C85,5.093 85.902,3.414 87.246,2.088 88.504,0.813 90.256,0 92.024,0 L0,0 0,7 85,7 C85,7 85,6.979 85,6.964 z" Stretch="Fill" HorizontalAlignment="Left" Width="92.024" Height="6.667" VerticalAlignment="Top"/>
    <Rectangle Fill="#FF939497" Margin="0,18.668,0,0" HorizontalAlignment="Left" Width="84.995"/>
    <Rectangle Fill="#FF939497" HorizontalAlignment="Left" Height="12" Margin="92.024,0,0,0" VerticalAlignment="Top" Width="329.976"/>
    <Path Data="M12,0.001 L92.023998,0.001 L92.023998,12.001 L12,12.001 z M0,12 C0,5.3725824 5.3725824,4.7497451E-11 12,4.7497451E-11 L12,12 z" Fill="#FF939497" HorizontalAlignment="Left" Height="12" Stretch="Fill" VerticalAlignment="Top" Width="92.024"/>
    </Grid>


    so nun kommt der knack punkt.

    ich möchte nun das das obere Rechteck über ein Property eine andere Höhe bekommt und auch das Untere Rechteck soll über ein Property eine andere breite bekommen. Bei dieser Änderungen müssen aber die zwei Kreisbögen aber weiterhin in der selben weise verändern. damit immer oberer Kreis r=höhe oberes Rechteck und Unterkreis r=r(vom oberenkreis) / 2

    wie bewerkstelligt man den so was?

    Freitag, 26. September 2014 09:35

Antworten

  • Hallo,die wohl beste Möglichkeit ist das Binden der einzelnen Werte im Pfad. Dafür musst du die Pfaddaten wieder in ein leicht leserliches Format wie folgendes Bringen und dann die Werte binden:

    <Path HorizontalAlignment="Left" Height="12" Stretch="Fill" VerticalAlignment="Top" Width="92.024">
        <Path.Data>
            <PathGeometry>
                <PathFigure StartPoint="{Binding StartPoint}">
                    <LineSegment Point="{Binding ZielPointXY}"/>
                    <LineSegment Point="{Binding ZielPoint2XY}"/>
                </PathFigure>
            </PathGeometry>
        </Path.Data>
    </Path>

    Die exakten Werte musst du dann einbauen und binden. Dabei muss man teilweise etwas um die Ecke denken, damit sich nichts falsch verzehrt. (Ich weiß von was ich rede)

    Deutlich einfacher wird das Ganze durch das Einsetzen eines Grids.

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="10"/>
            <RowDefinition Height="50"/>
            <RowDefinition Height="10"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="10"/>
            <ColumnDefinition Width="80"/>
            <ColumnDefinition Width="10"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Rectangle Fill="#FF939497" Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="3" Grid.RowSpan="2"/>
        <Rectangle Fill="#FF939497" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Grid.RowSpan="3"/>
        <Path Fill="#FF939497" StrokeThickness="0">
            <Path.Data>
                <PathGeometry>
                    <PathFigure StartPoint="10 0">
                        <LineSegment Point="10 10"/>
                        <LineSegment Point="0 10"/>
                        <ArcSegment Point="10 0" Size="10 10" SweepDirection="Clockwise"/>
                    </PathFigure>
                </PathGeometry>
            </Path.Data>
        </Path>
        <Path Fill="#FF939497" StrokeThickness="0" Grid.Row="2" Grid.Column="2">
            <Path.Data>
                <PathGeometry>
                    <PathFigure StartPoint="10 0">
                        <LineSegment Point="0 0"/>
                        <LineSegment Point="0 10"/>
                        <ArcSegment Point="10 0" Size="10 10" SweepDirection="Clockwise"/>
                    </PathFigure>
                </PathGeometry>
            </Path.Data>
        </Path>
    </Grid>
    Hier müsstest du dir nur noch die ganzen 10 durch entsprechende Bindungen ersetzen. Beachte, das Size einen Size-Wert und die Punkte einen Point-Wert erwarten. Du kannst also nicht einfach überall ein Double einbringen.


    Tom Lambert - C# MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    • Als Antwort vorgeschlagen Jens Gerber Freitag, 26. September 2014 13:07
    • Als Antwort markiert Tavok Dienstag, 30. September 2014 07:30
    Freitag, 26. September 2014 12:50
    Moderator
  • Hallo,
    zunächst muss deine Klasse die INotifyPropertyChanged-Schnittstelle implementieren. Damit kannst du die GUI über eine Änderung benachrichtigen.

    //using System.ComponentModel;
    public partial class MainWindow : Window, INotifyPropertyChanged{
        #region INotifyPropertyChanged Members
    
        protected void OnPropertyChanged(string propertyName)
        {
            var evt = this.PropertyChanged;
            if (evt != null)
                evt(this, new PropertyChangedEventArgs(propertyName));
        }
        public event PropertyChangedEventHandler PropertyChanged;
    
        #endregion

    Nun kannst du deine Eigenschaften implementieren. Diese müssen alle folgenden Aufbau haben:

    private double _Width;
    public double Width
    {
        get
        {
            return this._Width;
        }
        set
        {
            if (this._Width != value)
            {
                this._Width = value;
                this.OnPropertyChanged("Width");
            }
        }
    }

    Inhaltlich heißt das, dass die OnPropertyChanged-Methode aufgerufen wird, wenn sich der Eigenschaftswert ändert. Dadurch wird wiederum die GUI aktualisiert.
    Nun brauchst du verschiedene Eigenschaften:

    • double für normale Längenangaben.
    • GridLength für Spalten- und Zeilengrößen im Grid
    • Size für Größenangaben
    • Point für Punkte

    Alle diese Eigenschaften müssen public sein. Dann kannst du sie im XAML binden:

    <PathFigure StartPoint="{Binding PathStartPoint}">
        <LineSegment Point="{Binding Path1Point1}"/>
        <LineSegment Point="{Binding Path1Point2}"/>
        <ArcSegment Point="{Binding PathStartPoint}" Size="{Binding Path1Size}" SweepDirection="Clockwise"/>
    </PathFigure>
    Du musst für alle Werte, welche unterschiedlich sein können, entsprechende Eigenschaften anlegen und diese binden.


    Tom Lambert - C# MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    • Als Antwort vorgeschlagen Jens Gerber Dienstag, 30. September 2014 16:39
    • Als Antwort markiert Tavok Donnerstag, 9. Oktober 2014 12:48
    Dienstag, 30. September 2014 14:52
    Moderator

Alle Antworten

  • Hallo,die wohl beste Möglichkeit ist das Binden der einzelnen Werte im Pfad. Dafür musst du die Pfaddaten wieder in ein leicht leserliches Format wie folgendes Bringen und dann die Werte binden:

    <Path HorizontalAlignment="Left" Height="12" Stretch="Fill" VerticalAlignment="Top" Width="92.024">
        <Path.Data>
            <PathGeometry>
                <PathFigure StartPoint="{Binding StartPoint}">
                    <LineSegment Point="{Binding ZielPointXY}"/>
                    <LineSegment Point="{Binding ZielPoint2XY}"/>
                </PathFigure>
            </PathGeometry>
        </Path.Data>
    </Path>

    Die exakten Werte musst du dann einbauen und binden. Dabei muss man teilweise etwas um die Ecke denken, damit sich nichts falsch verzehrt. (Ich weiß von was ich rede)

    Deutlich einfacher wird das Ganze durch das Einsetzen eines Grids.

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="10"/>
            <RowDefinition Height="50"/>
            <RowDefinition Height="10"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="10"/>
            <ColumnDefinition Width="80"/>
            <ColumnDefinition Width="10"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Rectangle Fill="#FF939497" Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="3" Grid.RowSpan="2"/>
        <Rectangle Fill="#FF939497" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Grid.RowSpan="3"/>
        <Path Fill="#FF939497" StrokeThickness="0">
            <Path.Data>
                <PathGeometry>
                    <PathFigure StartPoint="10 0">
                        <LineSegment Point="10 10"/>
                        <LineSegment Point="0 10"/>
                        <ArcSegment Point="10 0" Size="10 10" SweepDirection="Clockwise"/>
                    </PathFigure>
                </PathGeometry>
            </Path.Data>
        </Path>
        <Path Fill="#FF939497" StrokeThickness="0" Grid.Row="2" Grid.Column="2">
            <Path.Data>
                <PathGeometry>
                    <PathFigure StartPoint="10 0">
                        <LineSegment Point="0 0"/>
                        <LineSegment Point="0 10"/>
                        <ArcSegment Point="10 0" Size="10 10" SweepDirection="Clockwise"/>
                    </PathFigure>
                </PathGeometry>
            </Path.Data>
        </Path>
    </Grid>
    Hier müsstest du dir nur noch die ganzen 10 durch entsprechende Bindungen ersetzen. Beachte, das Size einen Size-Wert und die Punkte einen Point-Wert erwarten. Du kannst also nicht einfach überall ein Double einbringen.


    Tom Lambert - C# MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    • Als Antwort vorgeschlagen Jens Gerber Freitag, 26. September 2014 13:07
    • Als Antwort markiert Tavok Dienstag, 30. September 2014 07:30
    Freitag, 26. September 2014 12:50
    Moderator
  • Hallo,

    Die Idee mit dem Grid ist super wusste gar nicht das mann es auch so verwenden kann.

    Nur das mit den Bindungen habe ich noch nicht so ganz verstanden wie das funktioniert in der WPF.

    Ich stelle mir das so vor:

    ich erstelle ein Property im c# code

    public int obereHöhe {get;set;}
    diesen wert möchte ich nun an das Grid binden und auch an die Points nur wie geht so etwas?

    Dienstag, 30. September 2014 08:53
  • Hallo,
    zunächst muss deine Klasse die INotifyPropertyChanged-Schnittstelle implementieren. Damit kannst du die GUI über eine Änderung benachrichtigen.

    //using System.ComponentModel;
    public partial class MainWindow : Window, INotifyPropertyChanged{
        #region INotifyPropertyChanged Members
    
        protected void OnPropertyChanged(string propertyName)
        {
            var evt = this.PropertyChanged;
            if (evt != null)
                evt(this, new PropertyChangedEventArgs(propertyName));
        }
        public event PropertyChangedEventHandler PropertyChanged;
    
        #endregion

    Nun kannst du deine Eigenschaften implementieren. Diese müssen alle folgenden Aufbau haben:

    private double _Width;
    public double Width
    {
        get
        {
            return this._Width;
        }
        set
        {
            if (this._Width != value)
            {
                this._Width = value;
                this.OnPropertyChanged("Width");
            }
        }
    }

    Inhaltlich heißt das, dass die OnPropertyChanged-Methode aufgerufen wird, wenn sich der Eigenschaftswert ändert. Dadurch wird wiederum die GUI aktualisiert.
    Nun brauchst du verschiedene Eigenschaften:

    • double für normale Längenangaben.
    • GridLength für Spalten- und Zeilengrößen im Grid
    • Size für Größenangaben
    • Point für Punkte

    Alle diese Eigenschaften müssen public sein. Dann kannst du sie im XAML binden:

    <PathFigure StartPoint="{Binding PathStartPoint}">
        <LineSegment Point="{Binding Path1Point1}"/>
        <LineSegment Point="{Binding Path1Point2}"/>
        <ArcSegment Point="{Binding PathStartPoint}" Size="{Binding Path1Size}" SweepDirection="Clockwise"/>
    </PathFigure>
    Du musst für alle Werte, welche unterschiedlich sein können, entsprechende Eigenschaften anlegen und diese binden.


    Tom Lambert - C# MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    • Als Antwort vorgeschlagen Jens Gerber Dienstag, 30. September 2014 16:39
    • Als Antwort markiert Tavok Donnerstag, 9. Oktober 2014 12:48
    Dienstag, 30. September 2014 14:52
    Moderator