Laden...

Attached Propertiesmithilfe generischer Basisklasse in einer Zeile erzeugen

Erstellt von CoderboyPB vor 4 Jahren Letzter Beitrag vor 2 Jahren 1.918 Views
C
CoderboyPB Themenstarter:in
327 Beiträge seit 2008
vor 4 Jahren
Attached Propertiesmithilfe generischer Basisklasse in einer Zeile erzeugen

Nachfolgenden Code habe ich aus diesem Video (bzw. dem zugehörigen GitHub Repository):
https://www.youtube.com/watch?v=trR5RQGEteM

Die Idee dahinter ist, Att. Prop. mit einer Zeile erzeugen zu können:

z.B.


public class SecurityIdProperty : BaseAttachedProperty<SecurityIdProperty, string> { }

Angewendet werden soll das dann z.B. so:


<TextBox local:SecurityIdProperty.Value="123" ... />

Jetzt aber kommt das, was ich nicht verstehe: Zum einen kennt XAML SecurityIdProperty nicht, statt dessen aber bietet mir die 'Intelligence' local:BaseAttachedProperty`2 an.

Vor allem das `2 lässt mich neugierig zurück ...

Das ganze ist ja nicht meine Idee, der Programmierer im Video macht es aber genau so ...

Irgendjemand ne Idee, was mir VS da sagen möchte?


public abstract class BaseAttachedProperty<Parent, Property>
        where Parent : BaseAttachedProperty<Parent, Property>, new()
    {
        #region Public Events

        /// <summary>
        /// Fired when the value changes
        /// </summary>
        public event Action<DependencyObject, DependencyPropertyChangedEventArgs> ValueChanged = (sender, e) => { };

        #endregion

        #region Public Properties

        /// <summary>
        /// A singleton instance of our parent class
        /// </summary>
        public static Parent Instance { get; private set; } = new Parent();

        #endregion

        #region Attached Property Definitions

        /// <summary>
        /// The attached property for this class
        /// </summary>
        public static readonly DependencyProperty ValueProperty = DependencyProperty.RegisterAttached("Value", typeof(Property), typeof(BaseAttachedProperty<Parent, Property>), new UIPropertyMetadata(new PropertyChangedCallback(OnValuePropertyChanged)));

        /// <summary>
        /// The callback event when the <see cref="ValueProperty"/> is changed
        /// </summary>
        /// <param name="d">The UI element that had it's property changed</param>
        /// <param name="e">The arguments for the event</param>
        private static void OnValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            // Call the parent function
            Instance.OnValueChanged(d, e);

            // Call event listeners
            Instance.ValueChanged(d, e);
        }

        /// <summary>
        /// Gets the attached property
        /// </summary>
        /// <param name="d">The element to get the property from</param>
        /// <returns></returns>
        public static Property GetValue(DependencyObject d) => (Property)d.GetValue(ValueProperty);

        /// <summary>
        /// Sets the attached property
        /// </summary>
        /// <param name="d">The element to get the property from</param>
        /// <param name="value">The value to set the property to</param>
        public static void SetValue(DependencyObject d, Property value) => d.SetValue(ValueProperty, value);

        #endregion

        #region Event Methods

        /// <summary>
        /// The method that is called when any attached property of this type is changed
        /// </summary>
        /// <param name="sender">The UI element that this property was changed for</param>
        /// <param name="e">The arguments for this event</param>
        public virtual void OnValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { }

        #endregion
    }

4.931 Beiträge seit 2008
vor 4 Jahren

Hast du denn in der XAML-Datei für local den passenden Namespace eingetragen?

BaseAttachedProperty2 ist die interne Bezeichnung, das dies eine generische Klasse ist (``` ist das Trennzeichen, da es nicht für .NET-Namen verwendent werden darf - und die Zahl dahinter ist die Anzahl der Parameter), s.a. [What&#39;s the meaning of “apostrophe + number” in the object type of properties with generics (eg. “Collection1”)?](https://stackoverflow.com/questions/6584263/whats-the-meaning-of-apostrophe-number-in-the-object-type-of-properties-wit)

C
CoderboyPB Themenstarter:in
327 Beiträge seit 2008
vor 4 Jahren

ja, der Namespace ist selbstverständlich eingetragen.
Das ist ja das Unverständliche.

C
CoderboyPB Themenstarter:in
327 Beiträge seit 2008
vor 4 Jahren

Komischerweise taucht der Namespace in der Liste beim setzen mit xmlns: doppelt in der Liste auf, wenn ich den zweiten wähle klappt es, beim ersten nicht. Ziemlich komisch. Scheint echt ein Fehler von VS zu sein.

1.040 Beiträge seit 2007
vor 4 Jahren

Komischerweise taucht der Namespace in der Liste beim setzen mit xmlns: doppelt in der Liste auf, wenn ich den zweiten wähle klappt es, beim ersten nicht. Ziemlich komisch. Scheint echt ein Fehler von VS zu sein.

Hä? 🤔
Kannst du mal bitte den XAML-Code zeigen?

C
CoderboyPB Themenstarter:in
327 Beiträge seit 2008
vor 4 Jahren

Zur Erklärung: der Code enthält ein Window Chrome, und das überschriebene Template der TextBox stammt aus einem anderen Beispiel, ich habe die jetzt drinnen gelassen, um den Code wirklich hier 1:1 wieder zu geben.


<Window x:Class="Facetto.Word.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:my="clr-namespace:Fasetto.Word"
        mc:Ignorable="d"
        AllowsTransparency="True"
        WindowStyle="None"
        Title="MainWindow" Height="450" Width="800">
    <WindowChrome.WindowChrome>
        <WindowChrome
            GlassFrameThickness="0"
            ResizeBorderThickness="4"
            CaptionHeight="36"
            />
    </WindowChrome.WindowChrome>
    <Window.Template>
        <ControlTemplate TargetType="Window">
            <Grid>
                <Border Padding="10"
                        Background="Blue"
                        CornerRadius="30"
                        x:Name="border"
                        >
                </Border>
                <ContentPresenter>
                    <ContentPresenter.OpacityMask>
                        <VisualBrush Visual="{Binding ElementName=border}"/>
                    </ContentPresenter.OpacityMask>
                </ContentPresenter>
            </Grid>
        </ControlTemplate>
    </Window.Template>
    <Grid>
        <TextBox Text="foooooo" Width="200" Height="50"
                 my:SecurityIdProperty.Value="123"
                 >
            
            <TextBox.Template>
                <ControlTemplate TargetType="TextBox">
                    <Grid Background="White">
                        <TextBox Text="{TemplateBinding Text}" FontSize="30"/>
                        <TextBlock 
                            Text ="{TemplateBinding my:SecurityIdProperty.Value}"
                            VerticalAlignment="Bottom"
                            HorizontalAlignment="Right"/>
                    </Grid>
                </ControlTemplate>
            </TextBox.Template>
        </TextBox>

    </Grid>
</Window>

Und hier der Screenshot mit dem doppelten Namespace:
Bild entfernt - Coffeebean [Hinweis] Wie poste ich richtig?, Punkt 6.1: Bilder als Dateianhang hochladen

5.657 Beiträge seit 2006
vor 4 Jahren

Der Namespace ist einmal als "Facetto" und einmal als "Fasetto" geschrieben. Schreibst du das alles mit der Hand?

Weeks of programming can save you hours of planning

C
CoderboyPB Themenstarter:in
327 Beiträge seit 2008
vor 4 Jahren

xaml ja, die BaseAttachedProperty nicht

Aber es lag wohl tatsächlich an den Namespaces, aber beide Namespaces existierten ja. Bissel komisch.
Hauptsache es geht jetzt.

Jetzt geht es an den nächsten Schritt: Den Teil mit den Events verstehen. Kann zwar Events, aber dieses rekursive generische macht es etwas komplizierter 😃

5.657 Beiträge seit 2006
vor 4 Jahren

Ich kann mir ehrlich gesagt keinen Anwendungsfall vorstellen, wo so etwas benötigt wird. Kannst du mal beschreiben, was du _eigentlich _vor hast?

Weeks of programming can save you hours of planning

C
CoderboyPB Themenstarter:in
327 Beiträge seit 2008
vor 4 Jahren

Lernen, Lernen, Lernen ...
Praktische Gehversuche:

Am Anfang ein eigenes überschriebenes Window Chrome

Das Beispiel der überschriebenen TextBox stammt aus diesem Artikel als Beispiel für die Verwendung einer Attached Property:
https://www.codemag.com/article/1405061

Und aus dem bereits genannten YT Video stammt die BaseAttachedProperty, mit welcher ich dann die normale A-Propperty ersetzt habe.

Nen Sinn steckt da tatsächlich nicht hinter. Außer wie gesagt halt, der Lernprozess, denn ich möchte jeden Tag etwas besser werden. Das ist mein Ziel.

Und das Hauptziel ist, ich will wieder arbeiten, leider ist es schwer mit meinen gesundheitlichen Einschränkungen, aber ich denke ich habe gute Chancen bei meinem Ex Arbeitgeber auf Minijob Basis unterzukommen.

5.657 Beiträge seit 2006
vor 4 Jahren

Ich glaube, du verrennst dich da in etwas. Das alles hat keinerlei praktische Relevanz. Lerne doch lieber Sachen, die man auch anwenden kann. Erfahrung mit MVVM bpsw. kann man in _jedem _WPF-Projekt gebrauchen.

Weeks of programming can save you hours of planning

C
CoderboyPB Themenstarter:in
327 Beiträge seit 2008
vor 4 Jahren

MVVM habe ich inzwischen komplett verstanden, bin dabei auch auf Caliburn.Micro gestoßen, hatte mich überzeugt

5.657 Beiträge seit 2006
vor 4 Jahren

Das ist nicht was ich meinte. Wenn du weißt, wie ein Klavier funktioniert, dann heißt das noch lange nicht, daß du es auch spielen kannst.

Versuch doch einfach mal, ein komplettes Projekt umzusetzen. Sowas wie eine einfache Todo-Liste oder ein Spiel wie MineSweeper. Das würde dir eine Menge praktischer Erfahrung einbringen. Das kannst du alles mit WPF und MVVM umsetzen, und alle Funktionien mit Unit-Tests abdecken. Mit einem solchen Projekt kannst du dich dann für einen Job bewerben.

Ich arbeite mit WPF seitdem es das gibt, und habe Anwendungen aus den unterschiedlichsten Bereichen damit umgesetzt. Und ich habe dafür nie ein Windows Chrome oder ein Attached Property erstellen müssen. Und wenn man es doch mal benötigt, kann man nachschauen, wie es geht. Viel wichtiger ist die Erfahrung, die man nur mit richtigen Projekten sammeln kann.

Weeks of programming can save you hours of planning

D
1 Beiträge seit 2021
vor 2 Jahren

Könnten Sie mir bitte sagen, wie Sie dieses Problem gelöst haben. Ich sitze schon lange an diesem Problem und habe keine Lösung gefunden. Wie bekomme ich Intellisense dazu, die benutzerdefinierten angehängten attached properties? Meine Anwendung wirft einen Fehler, der besagt:

Fehlermeldung:
... the method or operation is not implemented.

Das Bild Ihrer Lösung, die ich glaube, Sie hier hinzugefügt ist nicht mehr verfügbar ...
Thanks!

C
CoderboyPB Themenstarter:in
327 Beiträge seit 2008
vor 2 Jahren

Habe dorogz via PM geholfen.

Falls sich mal wieder jemand hier hin verirrt: Habe es eben gerade, nachdem ich das Projekt wieder neu gemacht hatte mit einem 'Projektmappe neu erstellen' sehr schnell lösen können.

F
10.010 Beiträge seit 2004
vor 2 Jahren

Bitte keine antworten per PM.
Du hast bestimmt auch schon antworten einfach hier gefunden, so klappt das aber nicht.