Tooltip in GridControl aus unangezeigter Spalte erstellen (DevExpress/WPF)

Für das GridControl in WinForms existiert eine sehr schöne Möglichkeit mittels ToolTipController einen Tooltip aus einer unsichtbaren Spalte der dahinterliegenden Datenquelle zu erstellen: Anleitung. In Wpf gibt’s keinen ToolTipController, weshalb man das ein bisschen anders machen muss (Quelle):

Zur besseren Orientierung findet sich im Folgenden ein großer Teil des XML-Baums, relevant ist eigentlich nur der Knoten „

    <dxb:BarManager x:Name="barManager" dxbh:BlendHelperForBarsAndRibbon.IsDesignControl="true">
        <DockPanel>
            <dxd:DockLayoutManager x:Name="dockLayoutManager">
                <dxd:LayoutGroup>
                    <dxd:TabbedGroup Name="tgProperties" ItemWidth="*" SelectedTabIndex="1">
                        <dxd:LayoutPanel Caption="Available Parameter" >
                            <dxg:GridControl x:Name="gridAvailableParameter" AutoPopulateColumns="True" HorizontalAlignment="Stretch" ItemsSource="{Binding ShownParametersInAvailableParameterGrid}" Margin="0,0,0,0" VerticalAlignment="Stretch">
                                <dxg:GridControl.Columns>
                                    <dxg:GridColumn FieldName="IrgendeinText">
                                        <dxg:GridColumn.CellTemplate>
                                            <DataTemplate>
                                                <dxe:TextEdit Name="PART_Editor">
                                                    <ToolTipService.ToolTip>
                                                        <Binding Path="Data.DazugehörigeToolTippText"/>
                                                    </ToolTipService.ToolTip>
                                                </dxe:TextEdit>
                                            </DataTemplate>
                                        </dxg:GridColumn.CellTemplate>
                                    </dxg:GridColumn>
                                <dxg:GridControl.View>
                                    <dxg:TableView BestFitMode="AllRows" BestFitArea="Header" AllowBestFit="True" AutoWidth="True" VerticalAlignment="Stretch" x:Name="tblParamList" ShownEditor="TableViewAvailableParameterBoxShown" HiddenEditor="TableViewAvailableParameterBoxHidden" ShowTotalSummary="True"/>
                                </dxg:GridControl.View>
                            </dxg:GridControl>
                        </dxd:LayoutPanel>                    
                    </dxd:TabbedGroup>
                </dxd:LayoutGroup>
            </dxd:DockLayoutManager>
        </DockPanel>
    </dxb:BarManager>

Reference Manager (Visual Studio) erklärt

Reference Manager - Microsoft Visual Studio

Assemblies

Hier finden sich die dlls aus dem Ziel-Framework (bei mir .NET). Unterschied zwischen .NET und COM-Framework.

Unter der Spalte ‚Name‘ steht die Dateibeschreibung der .dll:

Reference Manager 2

Framework

Assemblies, die das Ziel-Framework (bei mir .NET) ausmachen. Bei mir befinden sich die angezeigten Assemblies hier: C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5

Extensions

Assemblies von Drittanbietern

Per Tooltip kann man die Dateipfade der Assemblies sehen:

Reference Manager 3

Über die Auswahl der unter ‚Extensions‘ erscheinenden Assemblies entscheiden mehrere Registry-Variablen. Je höher die Framework-Version, desto mehr potenzielle Quellen gibt es. Die genaue Regel steht hier unter „2. Extension …“, wobei v.a. das Beispiel erhellend ist.

Es ist ratsam um die sog. Dll-Hell zu vermeiden, einen eigenen Ordner anzulegen, und die Referenzen konsequent nur aus diesem zu ziehen.

Recent

Die in letzter Zeit hinzugefügten Assemblies. Hier tauchen auch die in anderen Projekten hinzugefügten References auf.

Projects

Hier finden sich die anderen Projekte der aktuellen Solution. Eine goldene Regel lautet, dass man Projekte immer über diesen Weg referenzieren sollte.

COM

Hier finden sich die dlls aus dem COM-Framework. Unterschied zum .NET-Framework.

 

Best Practice

In einer solution mit mehrere Projekten, stopft man alle 3rd-party-dlls in einen separaten Ordner und referenziert diese dann mit Specific Version ‚false‘. Wenn man eine neue 3rd-Party-Version benutzen muss, dann kann man diese einfach im separaten Ordner austauschen. Einziger Wermutstropfen ist, dass man dann später nicht mehr den exakten Zustand der solution bestimmen kann.

C# Syntax verstehen: public MyMethod (int value) : base(value) { … }

Das wird auch base-Konstruktor genannt. Wird der base-Konstruktor aufgerufen, dann wird zuerst dessen Code ausgeführt und dann erst der Code des abgeleiteten Konstruktors. Ein Beispiel zum Verständnis:

using System;
using System.Threading;

    class Program
    {
        static void Main(string[] args)
        {
            new BaseClass("Called by initialisation of BaseClass");
            new DerivedClass("Called by initialisation of DerivedClass");
            Thread.Sleep(10000); // wenn dieser Code in einem 'Console Application'-Projekt drin ist, dann kann man sich so den Output 10 Sekunden lang anschauen. 
        }
    }

    class BaseClass
    {
        public BaseClass(string value)
        {
            Console.WriteLine("Constructor of base class. " + value);
        }
    }

    class DerivedClass : BaseClass
    {
        public DerivedClass(string value) : base(value)
        {
            Console.WriteLine("Constructor of derived class. " + value);
        }
    }

In der Konsole wird ausgegeben:

Constructor of base class. Called by initialisation of BaseClass
Constructor of base class. Called by initialisation of DerivedClass
Constructor of derived class. Called by initialisation of DerivedClass

DataContext im data binding-Konzept (WPF)

Der DataContext ist die default Quelle Deiner bindings. Ist er gesetzt, wird er innerhalb der Control-Hierarchie (beginnend mit Window) nach unten vererbt. Jedes WPF-Control hat sein eigenes DataContext-property, sodass man auf jeder Vererbungsebene die Vererbungshierarchie durchbrechen und ab dort eine neue Vererbungshierarchie etablieren kann. Wird der DataContext nicht gesetzt ist er null.

Der DataContext kann auf verschiedene Arten an verschiedenen Stellen erstellt werden (was es nicht gerade leichter macht, den Gesamtüberblick zu behalten):

DataContext via Window.DataContext

<Window x:Class="SampleApplication.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525" DataContext="{Binding Employee}">

bzw.

<Window x:Class="Example.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:l="clr-namespace:Example" Title="Example" Height="300" Width="300" Name="Main">

 <Window.DataContext>
     <StaticResource ResourceKey="data"/>
 </Window.DataContext>

Ziemlich gute Darstellung des Zusammenspiels von Window.DataContext, Window.Resources und einem WPF-Control: http://stackoverflow.com/a/1959701/1777526

DataContext in einem untergeordneten WPF-control

<UserControl DataContext="{Binding RelativeSource={RelativeSource Self}}">

Quelle

DataContext in der Codebehind-Datei

    public MainWindow()
    {
        (...)
        gridOfNames.DataContext = new ParameterDataSource();
        (...)
    }

Häufig wird die zu entwickelnde GUI selbst als DataContext gesetzt, wobei es zwei Wege gibt:

1.) im XAML

<Window x:Class="MyClass"
  Title="{Binding windowname}"
  DataContext="{Binding RelativeSource={RelativeSource Self}}"
  Height="470" Width="626">

weiterführende Quelle

2.) im Codebehind

public class MyWindow : Window {

    public MyWindow() {
        InitializeComponents();
        DataContext = this;
    }   
}

Weiterführende Quelle mit gutem Anwendungsbeispiel

Binding-Quellen jenseits vom DataContext

Braucht man eine Binding-Quelle nur für ein UI-control (und nicht für dessen Nachkommencontrols in der Vererbungshierarchie) kann man diese individuell setzen. Ein gg.falls existierender DataContext wird dadurch für dieses UI-Control überschrieben. Z.B. mit ‚ElementName‘ welches direkt zu einem anderen UI-Element bindet:

<Window x:Class="WpfTutorialSamples.DataBinding.HelloBoundWorldSample" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="HelloBoundWorldSample" Height="110" Width="280">
    <StackPanel Margin="10">
         <TextBox Name="txtValue" />
         <WrapPanel Margin="0,10">
             <TextBlock Text="Value: " FontWeight="Bold" />
             <TextBlock Text="{Binding Path=Text, ElementName=txtValue}" />
         </WrapPanel>
     </StackPanel>
</Window>

… oder mit dem Source-Property, welches z.B. zu einer Window.Ressource bindet:

<Window
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:src="clr-namespace:SDKSample"
  SizeToContent="WidthAndHeight"
  Title="Simple Data Binding Sample">

  <Window.Resources>
    <src:Person x:Key="myDataSource" PersonName="Joe"/>
  </Window.Resources>
  (...)
  <TextBlock Text="{Binding Source={StaticResource myDataSource}, Path=PersonName}"/>
  (...)
</Window>