Erstes-Control Codeverbesserung

  • WPF

Es gibt 14 Antworten in diesem Thema. Der letzte Beitrag () ist von Facebamm.

    Erstes-Control Codeverbesserung

    Hallö,

    Ich ein Gernerelles Problem mit dem TabController und hab mir mal so ein bisschen mein eigenen TabController gebaut und wolle mal wissen ob das so machen kann :D
    Ich hab es so Dynamisch wie möglich gestaltet.

    Das ganze Basiert auf ein Grid in dem ein Label und ein Canvas lagert.
    Das system ist so: Tab-Kopf erstellen, dazu eine Page, bei klick wird die Page zurück gegeben.
    Diese kann dann in einem Frame dargestellt werden.

    Spoiler anzeigen

    C#-Quellcode

    1. /// <summary>
    2. /// Interaktionslogik für TabHeader.xaml
    3. /// </summary>
    4. public partial class TabHeader : UserControl
    5. {
    6. private Label HeaderTitle { get => TitleLabel; set => TitleLabel = value; }
    7. private Canvas Underline { get => UnderlineUx; set => UnderlineUx = value; }
    8. private static GridLength TitleGridLength = new GridLength(27, GridUnitType.Star);
    9. private static GridLength UnderLineGridLength = new GridLength(3, GridUnitType.Star);
    10. private static GridLength NoneUse = new GridLength(0, GridUnitType.Pixel);
    11. private static GridLength NullUse = new GridLength(1, GridUnitType.Star);
    12. public Page TabPage { get; set; }
    13. public event EventHandler<Page> OnClick;
    14. #region Title
    15. public string Title{
    16. get => HeaderTitle.Content as string;
    17. set => HeaderTitle.Content = value;
    18. }
    19. public SolidColorBrush TitleColor {
    20. get => HeaderTitle.Foreground as SolidColorBrush;
    21. set => HeaderTitle.Foreground = value;
    22. }
    23. #endregion
    24. #region Underline
    25. #region Private
    26. private SolidColorBrush _NoneColor;
    27. private bool _IsSelect = false;
    28. private linePosition _UnderlinePosition = linePosition.Bottom;
    29. #endregion
    30. #region Propertys
    31. [Category("Underline")]
    32. public SolidColorBrush SelectColor { get; set; }
    33. [Category("Underline")]
    34. public SolidColorBrush NoneColor { get => _NoneColor; set { _NoneColor = value; Underline.Background = value; } }
    35. [Category("Underline")]
    36. public SolidColorBrush HoverColor { get; set; }
    37. [Category("Underline")]
    38. public bool IsSelect{ get => _IsSelect; set => Set_IsSelect(value); }
    39. [Category("Underline")]
    40. public double UnderlineHeight{ get => Underline.Height; set => SetUnderlineHeight(value); }
    41. [Category("Underline")]
    42. public double UnderlineWidth { get => Underline.Width; set => SetUnderlineWidth(value); }
    43. [Category("Underline")]
    44. public linePosition UnderlinePosition { get => _UnderlinePosition; set => SetUnderlinePosition(value); }
    45. #endregion
    46. #region Method
    47. private void SetUnderlinePosition(linePosition value)
    48. {
    49. _UnderlinePosition = value;
    50. switch (_UnderlinePosition)
    51. {
    52. case linePosition.Top:
    53. SetupRow(UnderLineGridLength, TitleGridLength);
    54. SetupColumns(NullUse, NoneUse);
    55. SetupUIelement(Underline, 0, 0);
    56. SetupUIelement(HeaderTitle, 0, 1);
    57. break;
    58. case linePosition.Right:
    59. SetupRow(UnderLineGridLength, NoneUse);
    60. SetupColumns(TitleGridLength, UnderLineGridLength);
    61. SetupUIelement(Underline, 1, 0);
    62. SetupUIelement(HeaderTitle, 0, 0);
    63. break;
    64. case linePosition.Bottom:
    65. SetupRow(TitleGridLength, UnderLineGridLength);
    66. SetupColumns(NullUse, NoneUse);
    67. SetupUIelement(Underline, 0, 1);
    68. SetupUIelement(HeaderTitle, 0, 0);
    69. break;
    70. case linePosition.Left:
    71. SetupRow(UnderLineGridLength, NoneUse);
    72. SetupColumns(UnderLineGridLength, TitleGridLength);
    73. SetupUIelement(Underline, 0, 0);
    74. SetupUIelement(HeaderTitle, 1, 0);
    75. break;
    76. }
    77. }
    78. private void SetUnderlineWidth(double value)
    79. {
    80. int colunm = Grid.GetColumn(Underline);
    81. if (_UnderlinePosition == linePosition.Left || _UnderlinePosition == linePosition.Right)
    82. _57814_.ColumnDefinitions[colunm].Width = double.IsNaN(value) ? UnderLineGridLength : new GridLength(value, GridUnitType.Pixel);
    83. Underline.Width = value;
    84. }
    85. private void SetUnderlineHeight(double value)
    86. {
    87. int row = Grid.GetRow(Underline);
    88. if (_UnderlinePosition == linePosition.Top || _UnderlinePosition == linePosition.Bottom)
    89. _57814_.RowDefinitions[row].Height = double.IsNaN(value) ? UnderLineGridLength : new GridLength(value, GridUnitType.Pixel);
    90. Underline.Height = value;
    91. }
    92. private void Set_IsSelect(bool value) {
    93. _IsSelect = value;
    94. Underline.Background = _IsSelect ? SelectColor : NoneColor;
    95. }
    96. private void SetNoneColor(SolidColorBrush value) {
    97. _NoneColor = value;
    98. Underline.Background = _NoneColor;
    99. }
    100. #endregion
    101. #endregion
    102. public enum linePosition
    103. {
    104. Top, Left, Right, Bottom
    105. }
    106. public TabHeader() : base()
    107. {
    108. InitializeComponent();
    109. HeaderTitle = TitleLabel;
    110. Underline = UnderlineUx;
    111. }
    112. public void SetHoverColor()
    113. {
    114. Underline.Background = HoverColor;
    115. }
    116. public void SetNoneColor()
    117. {
    118. Underline.Background = IsSelect ? SelectColor : NoneColor;
    119. }
    120. public void SetSelcted()
    121. {
    122. IsSelect = true;
    123. Underline.Background = SelectColor;
    124. }
    125. private void SetupRow(GridLength Row_0, GridLength Row_1)
    126. {
    127. RowDefinitionCollection rdc = _57814_.RowDefinitions;
    128. rdc[0].Height = Row_0;
    129. rdc[1].Height = Row_1;
    130. }
    131. private void SetupColumns(GridLength Column_0, GridLength Column_1)
    132. {
    133. ColumnDefinitionCollection cdc = _57814_.ColumnDefinitions;
    134. cdc[0].Width = Column_0;
    135. cdc[1].Width = Column_1;
    136. }
    137. private void SetupUIelement(UIElement element, int Column, int row)
    138. {
    139. Grid.SetColumn(element, Column);
    140. Grid.SetRow(element, row);
    141. }
    142. protected override void OnMouseEnter(MouseEventArgs e)
    143. {
    144. SetHoverColor();
    145. base.OnMouseEnter(e);
    146. }
    147. protected override void OnMouseLeave(MouseEventArgs e)
    148. {
    149. SetNoneColor();
    150. base.OnMouseLeave(e);
    151. }
    152. protected override void OnMouseDown(MouseButtonEventArgs e)
    153. {
    154. SetSelcted();
    155. if(OnClick != null)
    156. OnClick(this, TabPage);
    157. base.OnMouseDown(e);
    158. }
    159. }
    @Facebamm

    Frage:

    MVVM ist für dich kein Thema ?

    ​Ist das C# ?

    C#-Quellcode

    1. ​public string Title{
    2. get => HeaderTitle.Content as string;
    3. set => HeaderTitle.Content = value;
    4. }


    Gruss

    mikeb69
    Ich würde sagen das kam mit c# 7.0 aber ich find es gerade nicht mehr :D

    So zu MVVM
    Also leg ich ein Normale Klasse an, die Alle Eigenschaften des Objekts enthalten binde die in das Objekt ein und es bearbeit sich, irgendwie wie ich will :D

    Aber so kann man es jetzt bzw. sollte man es nicht machen ?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Facebamm“ ()

    Facebamm schrieb:

    @mikeb69

    Was genau MVVm ist schau ich gerade.

    und ja ist es :D


    Nein - ist es nicht.
    Nach MVVM würde man so sicherlich nicht ein UserControl gestalten.

    Ah - kann ja auch als Antwort auf die Frage "Ist MVVM ein Thema für dich?" verstanden werden - ja dann ergibt das sinn, wenn du das bejahst.
    Quasi: "Thema isses - aber noch nicht gelöst"
    @ErfinderDesRades

    "und ja ist es ", war auf die frage wegen C# bezogen.

    Aber so recht versteh ich MVVM nicht, denn im Editor kann ich diverse eigenschaften wie HoverColor ect. nicht mehr ändern und das verwirrt mich ein bisschen mit dem Binding.

    Zu der Aussage wegen dem UserControl, ja es ist ein UserControl was auf ein Label und einem Canvas basier.
    Ziel
    Label stellt den Text dar und das (ich nehm jetzt mal das Sächliche) Canvas ist halt das was Graphisch verändert wird, wenn die Maus über das UserControl fährt, oder hineinklick.
    Dabei möchte ich natürlich die Position vom Canvas, verändern können.

    :D
    Hi :D

    ich hab mir das mit dem MVVM nochmal zur Brust gezogen und häng gerade bei einem VM-Problem.

    Ich hab mein Model erstell
    Spoiler anzeigen

    C#-Quellcode

    1. namespace FaceControls
    2. {
    3. using System;
    4. using System.ComponentModel;
    5. using System.Windows.Media;
    6. using System.Windows.Controls;
    7. using System.Windows;
    8. class TabHeaderSetting : INotifyPropertyChanged
    9. {
    10. public event PropertyChangedEventHandler PropertyChanged;
    11. #region PropertSetting
    12. private Page _TabPage;
    13. [Category("Setting")]
    14. public Page TabPage { get => _TabPage; set => _TabPage = RaisEvent(value, nameof(TabPage)); }
    15. private bool _IsSelect;
    16. [Category("Setting")]
    17. public bool IsSelect { get => _IsSelect; set => _IsSelect = RaisEvent(value, nameof(_IsSelect)); }
    18. private bool _IsHover;
    19. [Category("Setting")]
    20. public bool IsHover { get => _IsHover; set => _IsHover = RaisEvent(value, nameof(IsHover)); }
    21. #endregion
    22. #region Title
    23. private string _Title;
    24. [Category("Title")]
    25. public string Text { get => _Title; set => _Title = RaisEvent(value, nameof(Text)); }
    26. public SolidColorBrush _TitleColor;
    27. [Category("Title")]
    28. public SolidColorBrush TitleColor { get => _TitleColor; set => _TitleColor = RaisEvent(value, nameof(TitleColor)); }
    29. public SolidColorBrush _TitleHover;
    30. [Category("Title")]
    31. public SolidColorBrush TitleHover { get => _TitleHover; set => _TitleHover = RaisEvent(value, nameof(TitleHover)); }
    32. public SolidColorBrush _TitleSelect;
    33. [Category("Title")]
    34. public SolidColorBrush TitleSelect { get => _TitleSelect; set => _TitleSelect = RaisEvent(value, nameof(TitleSelect)); }
    35. private VerticalAlignment _TextVerticalAlignment;
    36. [Category("Title")]
    37. public VerticalAlignment TextVerticalAlignment { get => _TextVerticalAlignment; set => _TextVerticalAlignment = RaisEvent(value, nameof(TextVerticalAlignment)); }
    38. private HorizontalAlignment _TextHorizontalAlignment;
    39. [Category("Title")]
    40. public HorizontalAlignment TextHorizontalAlignment { get => _TextHorizontalAlignment; set => _TextHorizontalAlignment = RaisEvent(value, nameof(TextHorizontalAlignment)); }
    41. #endregion
    42. #region Selector
    43. private Position _SelectorPosition;
    44. [Category("Marker")]
    45. public Position SelectorPosition { get => _SelectorPosition; set => _SelectorPosition = RaisEvent(value, nameof(SelectorPosition)); }
    46. private Brush _SelectorColor;
    47. [Category("Marker")]
    48. public Brush SelectorColor { get => _SelectorColor; set => _SelectorColor = RaisEvent(value, nameof(SelectorColor)); }
    49. private Brush _SelectorHover;
    50. [Category("Marker")]
    51. public Brush SelectorHover { get => _SelectorHover; set => _SelectorHover = RaisEvent(value, nameof(SelectorHover)); }
    52. private Brush _SelectorSelect;
    53. [Category("Marker")]
    54. public Brush SelectorSelect { get => _SelectorSelect; set => _SelectorSelect = RaisEvent(value, nameof(SelectorSelect)); }
    55. private double _SelectorWidth;
    56. [Category("Marker")]
    57. public double SelectorWidth { get => _SelectorWidth; set => _SelectorWidth = RaisEvent(value, nameof(SelectorWidth)); }
    58. private double _SelectroHeight;
    59. [Category("Marker")]
    60. public double SelectorHeight { get => _SelectroHeight; set => _SelectroHeight = RaisEvent(value, nameof(SelectorHeight)); }
    61. #endregion
    62. #region Event
    63. private TValue RaisEvent<TValue>(TValue value, string name)
    64. {
    65. PropertyChanged(this, new PropertyChangedEventArgs(name));
    66. return value;
    67. }
    68. private TValue RaisEvent<TValue>(TValue value, string name, Action action)
    69. {
    70. PropertyChanged(this, new PropertyChangedEventArgs(name));
    71. action();
    72. return value;
    73. }
    74. #endregion
    75. #region Setting
    76. [Flags]
    77. public enum Position
    78. {
    79. Left = 1,
    80. Right = 2,
    81. Top = 3,
    82. Bottom = 4
    83. }
    84. #endregion
    85. }
    86. }


    ich hab mein View erstellt

    Spoiler anzeigen

    Grund Idee


    In WPF umgesetzt (View.xaml)



    Was ist jetzt genau mein Problem?
    Bei der Idee ist untern der lila Balken, dieser soll sich je nach dem wo ich die Position anordne nach links, ... ,unten positionieren.
    Mein Idee war das ich den Balken einfach durch das Grid schalte.
    Wie setze ich das jetzt mit Binding um, ist das VM, das View.xaml.cs und hab ihr eine bessere Lösung da für (Code drunter)?

    Code
    Spoiler anzeigen

    Methode

    C#-Quellcode

    1. private TValue RaisEvent<TValue>(TValue value, string name)
    2. {
    3. PropertyChanged(this, new PropertyChangedEventArgs(name));
    4. return value;
    5. }

    Aufruf

    C#-Quellcode

    1. private string _Title;
    2. [Category("Title")]
    3. public string Text { get => _Title; set => _Title = RaisEvent(value, nameof(Text)); }

    Facebamm schrieb:

    hab ihr eine bessere Lösung da für (Code drunter)?
    Ich denke der Code ist so nicht ganz korrekt. Schau dir die Reihenfolge mal etwas genauer an. Wenn du das PropertyChanged Event feuerst sagst du der UI, dass sich das Property geändert hat und es holt sich den neuen Wert. Danach aber erst setzt du den neuen Wert. Also ich würde mir dafür eine Basisklasse schreiben und dann [CallerMemberName] benutzen um den Property Namen zu bekommen und den nicht immer mit übergeben zu müssen. In etwa so:

    C#-Quellcode

    1. public class PropertyChangedBase : INotifyPropertyChanged {
    2. public event PropertyChangedEventHandler PropertyChanged;
    3. protected void SetValueRaisEvent<T>(T value, ref T field, [CallerMemberName] string memberName = "") {
    4. field = value;
    5. PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(memberName));
    6. }
    7. }


    Dann würde es in deiner TabHeaderSetting Klasse etwa so aussehen:

    C#-Quellcode

    1. private bool _IsSelect;
    2. [Category("Setting")]
    3. public bool IsSelect { get => _IsSelect; set => SetValueRaisEvent(value, ref _IsSelect); }​
    @Bluespide Oh, hast völlig recht :D

    hab es jetzt geändert, dazu muss ich sagen das ich das Attribut nicht kannte :/ aber jetzt,
    und die Invoke-Sache ist auch gar nicht mal so blöd :D

    Danke :D

    Aber bisher ist mein logisches Problem mit dem MVVM noch nicht geklärt bzw ich hab es immer noch nicht raus wie ich den Balken Positioniere :/
    vlt. frag ich mal anders, kennt jm. eine sehr gute Lektüre für Anfänger++ in MVVM ?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Facebamm“ ()

    Frage ist auch, was du erreichen willst. Mir sieht das aus, als wollest du iwie ein Eigenbau-TabControl basteln.
    Aber Wpf kennt doch schon ein TabControl - ist iwas nicht gut daran?

    Weil evtl gehts garnet um Daten, dann wäre Viewmodel vlt. sogar garnet angesagt, sondern stattdessen müsstest du dich in Styles und ControlTemplates und Zeugs einarbeiten.
    - in Eigenbau-TabControl -
    Ich würde sagen das Trifft es genau.

    #Vorweg, ich weiß bei weiten noch nicht was alles in WPF möglich ist, bevorzuge ich lieber zu beschreiben was ich wünsche :D

    Also ...
    wenn ich mit der Maus über den TabTitle (Das ding wo der Name der Seite steht, wie im Browser der Title), dann soll eine Balken unter dem TabTitle erscheinen in einer Farbe (Selbst wähl bar im Desginer).
    Balken der Balken soll zugleich nicht nur unter dem TabTitle sondern auch noch Links, Rechts, Oben und Unten Positioniert werden können, zugleich sollen aber auch mehrere möglichkeiten gehen wie Links und Unten oder Links und Rechts - Dann wäre der Balken also links und rechts neben dem TabTitle zu sehen.
    Das gleiche Spiel für die Selektion eines Tabs.
    Der Balken soll Größen verstellbar sein.
    Weiterhin soll es möglich sein ein Icon hinzuzufügen, welches je nachdem wie man es möchte ab einer stimmten Größe erst angezeigt wird (also wenn es kleiner 32 px ist), dauerhaft hinter dem Title oder Garnicht.
    Icon soll Größen verstellbar sein.

    Der Inhalt eines Tabs soll in Page (Typ) sein.