Binding von DataTemplate in UserControl.Resources zu UserControl DataContext funktioniert nicht

  • WPF

Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von kaifreeman.

    Binding von DataTemplate in UserControl.Resources zu UserControl DataContext funktioniert nicht

    Hallo Leute,

    ich bin hier gerade etwas am verzweifeln. Ich habe ein DataTemplate in den Resourcen eines Usercontrols definiert:

    XML-Quellcode

    1. <UserControl.Resources>
    2. <ResourceDictionary>
    3. <DataTemplate x:Key="PageFooterTemplate">
    4. <Grid>
    5. <TextBlock HorizontalAlignment="Left" FontSize="10" Text="{Binding Source={x:Static system:DateTime.Now}, StringFormat=d, ConverterCulture=de-AT}"/>
    6. <TextBlock HorizontalAlignment="Center" FontSize="10" Text="Provided by MySalesTool"/>
    7. <StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
    8. <TextBlock Margin="0,0,10,0" HorizontalAlignment="Right" VerticalAlignment="Center" FontSize="10" Text="{lex:Loc Key=offer_page}"/>
    9. <TextBlock Margin="0,0,0,0" HorizontalAlignment="Right" VerticalAlignment="Center" FontSize="10">
    10. <TextBlock.Text>
    11. <Binding Path="PageIndex" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type syncfusion:PrintPageControl}}"/>
    12. </TextBlock.Text>
    13. </TextBlock>
    14. <TextBlock Text="{lex:Loc Key=of}" HorizontalAlignment="Right" VerticalAlignment="Center" FontSize="10"/>
    15. <TextBlock Margin="0,0,0,0" HorizontalAlignment="Right" VerticalAlignment="Center" FontSize="10">
    16. <TextBlock.Text>
    17. <Binding Path="TotalPages" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type syncfusion:PrintPageControl}}"/>
    18. </TextBlock.Text>
    19. </TextBlock>
    20. </StackPanel>
    21. </Grid>
    22. </DataTemplate>
    23. <DataTemplate x:Key="PageHeaderTemplate">
    24. <Grid DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:ItemsUcl}}, Path=DataContext}">
    25. <!--<TextBlock Text="{lex:Loc Key=items}" FontSize="18" HorizontalAlignment="Left"/>-->
    26. <TextBlock Width="120" Text="{Binding Path=DataContext.HeaderText, Mode=OneWay, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:ItemsUcl}}}" FontSize="18" HorizontalAlignment="Left"/>
    27. <Image x:Name="TenantImage" HorizontalAlignment="Right" Stretch="Fill" Width="250" Height="150" Source="{Binding Path=DataContext.TenantLogo, Mode=OneWay, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:ItemsUcl}}}"/>
    28. </Grid>
    29. </DataTemplate>
    30. </ResourceDictionary>
    31. </UserControl.Resources>

    Im Dictionary sind noch ein weiteres Template und einige andere "Sachen" die sollten aber damit nix zu tun haben.

    Im Kopf des Usercontrols ist der DataContext wie folgt hinterlegt:

    XML-Quellcode

    1. <UserControl x:Class="ItemsUcl"
    2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    5. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    6. xmlns:Fluent="clr-namespace:Fluent;assembly=Fluent"
    7. xmlns:FluentHelper="clr-namespace:View.RibbonHelper"
    8. FluentHelper:FluentRibbonHelper.RibbonTabGroup="{DynamicResource ribboncontextgroup}"
    9. FluentHelper:FluentRibbonHelper.RibbonTabDataContext="{Binding}"
    10. FluentHelper:FluentRibbonHelper.RibbonTab="{DynamicResource ribboncontextual}"
    11. xmlns:lex="http://wpflocalizeextension.codeplex.com"
    12. xmlns:VM="clr-namespace:ViewModel.ViewModels;assembly=ViewModel"
    13. xmlns:syncfusion="http://schemas.syncfusion.com/wpf"
    14. xmlns:syncGrid="clr-namespace:Syncfusion.UI.Xaml.Grid;assembly=Syncfusion.SfGrid.WPF"
    15. xmlns:i1="http://schemas.microsoft.com/xaml/behaviors"
    16. xmlns:system="clr-namespace:System;assembly=mscorlib"
    17. xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
    18. xmlns:interactivity="http://schemas.microsoft.com/xaml/behaviors"
    19. lex:LocalizeDictionary.DesignCulture="en"
    20. lex:ResxLocalizationProvider.DefaultAssembly="View"
    21. lex:ResxLocalizationProvider.DefaultDictionary="Strings"
    22. mc:Ignorable="d" d:DesignWidth="600" d:DesignHeight="600"
    23. xmlns:local="clr-namespace:View"
    24. d:DataContext="{d:DesignInstance IsDesignTimeCreatable=false,Type={x:Type VM:ItemsVM}}">


    Die Gesamtview bindet auch korrekt nur das DataTemplate findet im FindAncestor Mode das Usercontrol nicht.
    Ich habe versucht bis ins Ancestorlevel 13 zu gehen, ich habe Templated Parent versucht, ich habe versucht im Binding das Path= wegzulassen und in meiner Verzweiflung auch über Elementname.
    Die Properties sind im Viewmodel sauber definiert und binden korrekt.

    In den XAML Binding Failures wird angezeigt:

    Cannot find source: RelativeSource FindAncestor, AncestorType='View.ItemsUcl'

    Hat jemand eine Idee wie ich dem Template erklären kann wo es den Datacontext vom View finden soll? Danke
    mfG.
    Stephan
    Hallo

    Wo das DataTemplate verwendet wird sehe ich aus dem Code nicht heraus.
    Gehe ich richtig der Annahme das das DateTemplate im selben UserControl verwendet wird in welchem es definiert wurde? Also nicht das du ein UserControl in nem UserControl hast?
    Warum dann mit FindAncestor den DataContext holen wenn das die Controls innerhalb des DataTemplate diesen Vererbt bekommen?

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Hallo,

    das DataTemplate ist im selben Usercontrol in dem es auch verwendet werden soll.
    Ich habe schon langsam den Verdacht es liegt am Syncfusion.

    Was ich ja eigentlich erreichen möchte ist das ich im Codebehind das Datagrid über die Syncfusion funktion ausdrucke das schaut so aus:

    Ablauf:
    - Benutzer drückt Knopf im Ribbon
    - Ribbon Button ist gebunden an Command im Viewmodel (prüft Berechtigung usw.)
    - Viewmodel schickt Nachricht an die View, wenn der Uniquewindowhandler ein Match ist dann wird dieser Code aufgerufen:

    VB.NET-Quellcode

    1. Private Sub PrintMessageHandler(obj As Object)
    2. If obj.GetType = GetType(Guid) AndAlso DirectCast(obj, Guid).Equals(DirectCast(DataContext, MyMultiVMBaseSf).UniqueWindowHelper) Then
    3. 'UniqueWindowHandler is a match
    4. 'Header
    5. Dim vHeader As DataTemplate = CType(Me.Resources("PageHeaderTemplate"), DataTemplate)
    6. 'Footer
    7. Dim vFooter As DataTemplate = CType(Me.Resources("PageFooterTemplate"), DataTemplate)
    8. 'Define the Setup:
    9. Dim vPrintSettings As New PrintSettings With {.AllowColumnWidthFitToPrintPage = True,
    10. .AllowRepeatHeaders = True,
    11. .PrintScaleOption = PrintScaleOptions.FitAllColumnsonOnePage,
    12. .CanPrintStackedHeaders = True,
    13. .PrintPageOrientation = PrintOrientation.Landscape,
    14. .PrintPageFooterHeight = 20,
    15. .PrintPageFooterTemplate = vFooter,
    16. .PrintPageHeaderHeight = 150,
    17. .PrintPageHeaderTemplate = vHeader,
    18. .PrintPageMargin = New Thickness(37.8, 56.7, 37.8, 56.7)}
    19. ElementsDatagrid.PrintSettings = vPrintSettings
    20. Debug.Print(ElementsDatagrid.PrintSettings.PrintPageMargin.ToString) '96,96,96,96
    21. ElementsDatagrid.ShowPrintPreview()
    22. End If
    23. End Sub


    in der vHeader und vFooter wird das Datatemplate vom Usercontrol selbst geholt. Ich vermute schon langsam das hier der "Hund" begraben liegt, mit ElementsDatagrid.ShowPrintPreview, wird einen Druckvorschau aufgerufen und hier wäre der erste Zugriff auf das Viewmodel.
    Mein Plan B wäre jetzt die DataTemplates in der View über eine Helperklasse zu erstellen, die notwendigen Bindings (also ein Text und ein Byte()) als Payload in meine Message zu packen, oder via Cast aus dem Viewmodel zu holen und dann zu hoffen das es korrekt rendert.
    mfG.
    Stephan
    Hallo

    Also wenn das DataTemplate im selben UserControl ist dann würde ja meiner Meinung nach DataContext={Binding} genügen. =O
    Ansonsten kann ich zu dieser eher speziellen konstellation recht wenig sagen und mit SyncFusion habe ich unter WPF noch nicht gearbeitet.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Bin mir mittlerweile ziemlich sicher das es an Syncfusion liegt, ich hab das Binding nochmals "zurückgebaut" und bin auf die übliche Einstellung ohne FindAncestor gegangen, was ich im LiveVisualTree sehe ist folgendes:


    Der MainWS ist da wo ich arbeite (SpsWindow ist dir ja bekannt :D )
    Wenn die Vorschau geöffnet wird, erzeugt das System ein "chromeless Window" mit 2 Grids, also Header und Footer.
    Im Header Grid ist mein Textblock und mein Image zu finden. Auch das ItemsUcl wird im Live Property korrekt anzeigt.
    Rein optisch schaut das alles gut aus, also kann es nur mehr am Rendering Prozess vom Syncfusion hängen, ich werd da mal weiter schauen ob es in diese Richtung was gibt.


    Update ich hab eine Lösung gefunden:
    Es muss das Viewmodel in den Ressourcen definiert werden und dann das DataTemplate => Grid Datacontext auf diese Ressource eingestellt werden.

    XML-Quellcode

    1. <UserControl.Resources>
    2. <ResourceDictionary>
    3. <VM:ItemsVM x:Key="ViewModel"/>
    4. <DataTemplate x:Key="PageHeaderTemplate">
    5. <Grid DataContext="{StaticResource ViewModel}">
    6. <!--<TextBlock Text="{lex:Loc Key=items}" FontSize="18" HorizontalAlignment="Left"/>-->
    7. <TextBlock Background="Aqua" Width="120" Text="{Binding HeaderText, Mode=OneTime}" FontSize="18" HorizontalAlignment="Left"/>
    8. <Image x:Name="TenantImage" HorizontalAlignment="Right" Stretch="Fill" Width="250" Height="150" Source="{Binding TenantLogo, Mode=OneWay}"/>
    9. </Grid>
    10. </DataTemplate>
    11. </UserControl.Resources>
    12. </ResourceDictionary>


    Dann funktioniert es.... hat mich jetzt 2 Wochen gekostet das rauszufinden. :/
    Danke für eure Unterstützung.



    mfG.
    Stephan

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