We help IT Professionals succeed at work.

DataTemplate - How to binding from ViewModel (or without)

Plexo
Plexo asked
on
I have a DataTemplante, for use in a report header and footer ](see image 1 and 2 <<<).
I need that this DataTemplante binding from ViewModel. I am using a constant, but need to replace it programmatically.
My ViewModel is working, because my Page has a TextEdit binding from ViewModel (see image 3 <<<). But I could not do it in DataTemplante.
If you have any suggestions without ViewModel is welcome.

<UserControl.Resources>
        <data:SilverlightControl1Model x:Name="SilverlightControl1Model"/>
        <DataTemplate x:Key="PageHeader">
            <Grid>
                    <dxe:TextEdit
                           Text="Text1" ==> I tried <== Text="{Binding Cabecalho1}"  I tried <== Text="{Binding Path=Cabecalho1}"                          
                            dxp:ExportSettings.TargetType="Text"
                           HorizontalContentAlignment="Center"
                           Width="{Binding Path=UsablePageWidth, Mode=OneWay}"
                           Background="Transparent" Margin="0,0,0,0"/>
                    <dxe:TextEdit EditValue="Text2"
                           dxp:ExportSettings.TargetType="Text"
                           HorizontalContentAlignment="Left"
                           Background="Transparent" Margin="0,50,0,0"/>
                </Grid>
        </DataTemplate>
        <DataTemplate x:Key="PageFooter">
            <dxe:TextEdit                        
                         HorizontalContentAlignment="Center"
                         Width="{Binding Path=UsablePageWidth, Mode=OneWay}"
                         dxp:ExportSettings.TargetType="PageNumber"
                         dxp:PageNumberExportSettings.Kind="NumberOfTotal"
                         dxp:PageNumberExportSettings.Format="Página {0} de {1}" />
        </DataTemplate>
    </UserControl.Resources>

 Ilustration xaml.cs
 ViewModel.txt
xaml.txt
Comment
Watch Question

I believe that the problem is in this statement:
      <Grid x:Name="LayoutRoot" DataContext="{StaticResource SilverlightControl1Model}" >
This creates a new instance of SilverlightControl1Model and assigns it as the DataContext for the Grid and all its children.
A user control inherits the existing datacontext when it is added to a parent control.
Try this instead:
      <Grid x:Name="LayoutRoot">

Author

Commented:
Hi MikeToole,

Thanks for the feedback.
The problem is not in "LayoutRoot", He is working and putting what I want on the Page.
The problem is in <DataTemplate> in  <UserControl.Resources> above of it.
I have a Grid in it only for group two TextEdit.
AnyWay I put your suggestion DataContext="{StaticResource SilverlightControl1Model}" in Grid of DataTemplate, but still did not work.

Below is the highlight in bold.

Thanks.




<UserControl
    x:Class="SCE_Relatorios_V1.Views.SilverlightControl1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:dxp="http://schemas.devexpress.com/winfx/2008/xaml/printing"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"    
   
    mc:Ignorable="d"
    d:DesignWidth="1000" d:DesignHeight="580"

             xmlns:dxlc="http://schemas.devexpress.com/winfx/2008/xaml/layoutcontrol"
             xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
             xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors"
             xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid"
             xmlns:data="clr-namespace:SCE_Relatorios_V1.ViewModel">

    <UserControl.Resources>
        <data:SilverlightControl1Model x:Name="SilverlightControl1Model"/>
        <DataTemplate x:Key="PageHeader">
            <Grid DataContext="{StaticResource SilverlightControl1Model}"  >> Your suggestion is here <<
                    <dxe:TextEdit
                           EditValue="{Binding Cabecalho1, Mode=OneWay}"
                           dxp:ExportSettings.TargetType="Text"
                           HorizontalContentAlignment="Center"
                           Width="{Binding Path=UsablePageWidth, Mode=OneWay}"
                           Background="Transparent" Margin="0,0,0,0"/>
                    <dxe:TextEdit
                           EditValue="Text2"
                           dxp:ExportSettings.TargetType="Text"
                           HorizontalContentAlignment="Left"
                           Background="Transparent" Margin="0,50,0,0"/>
                </Grid>
        </DataTemplate>
        <DataTemplate x:Key="PageFooter">
            <dxe:TextEdit                        
                         HorizontalContentAlignment="Center"
                         Width="{Binding Path=UsablePageWidth, Mode=OneWay}"
                         dxp:ExportSettings.TargetType="PageNumber"
                         dxp:PageNumberExportSettings.Kind="NumberOfTotal"
                         dxp:PageNumberExportSettings.Format="Página {0} de {1}" />
        </DataTemplate>
    </UserControl.Resources>
     
 
        <Grid x:Name="LayoutRoot" DataContext="{StaticResource SilverlightControl1Model}"
                      >> Here is Functioning normaly <<
        <dxlc:GroupBox Header="groupBox1" HorizontalAlignment="Left" Name="groupBox1" VerticalAlignment="Top" Width="1000" Height="109">
            <Grid Name="grid1">
                <sdk:Label Height="Auto" HorizontalAlignment="Left" Margin="6,6,0,0" Name="label1" VerticalAlignment="Top" Width="Auto" Content="Data DE:" />
                <sdk:Label Height="Auto" HorizontalAlignment="Left" Margin="6,28,0,0" Name="label2" VerticalAlignment="Top" Width="Auto" Content="Data ATÉ:" />
                <Button Content="Pesquisar" Height="23" HorizontalAlignment="Left" Margin="596,28,0,0" Name="btnPesquisar" VerticalAlignment="Top" Width="75" Click="btnPesquisar_Click" />
                <Button Content="Relatório" Height="23" HorizontalAlignment="Left" Margin="721,28,0,0" Name="btnRelatório" VerticalAlignment="Top" Width="75" Click="btnRelatório_Click" />
                <dxe:DateEdit HorizontalAlignment="Left" Margin="72,6,0,0" Name="dateEdit1" VerticalAlignment="Top" Width="150" />
                <dxe:DateEdit HorizontalAlignment="Left" Margin="72,28,0,0" Name="dateEdit2" VerticalAlignment="Top" Width="150" />
                <Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="846,27,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" Command="{Binding btnIncluir}" />
               <dxe:TextEdit
                    Text="{Binding Cabecalho1}"
                    HorizontalAlignment="Left"
                    Margin="282,10,0,0" Name="textEdit1"
                    VerticalAlignment="Top"
                    Width="150" />

                      >> Here is Binding normaly <<
            </Grid>
        </dxlc:GroupBox>
        <dxg:GridControl HorizontalAlignment="Left" Margin="0,115,0,0" Name="gridControl1" VerticalAlignment="Top" Width="1000" Height="414">
            <dxg:GridControl.Columns>
                <dxg:GridColumn FieldName="Area" Header="Área" Name="gridColumnArea" Visible="False" Width="50" />
                <dxg:GridColumn FieldName="Grupo" Header="Grupo" Name="gridColumnGrupo" Visible="False" Width="60" />
                <dxg:GridColumn FieldName="SubGrupo" Header="SubGrupo" Name="gridColumnSubGrupo" Visible="False" Width="80" />
                <dxg:GridColumn FieldName="CodigoSacado" Header="Codigo do Sacado" Name="gridColumnCodigoSacado" Visible="False" Width="60" />
                <dxg:GridColumn FieldName="NomeSacado" Header="Nome do Sacado" Name="gridColumnNomeSacado" Visible="False" Width="300" />
                <dxg:GridColumn FieldName="CodigoSequencial" Header="Codigo Produto" Name="gridColumnCodigoSequencial" Width="120" />
                <dxg:GridColumn FieldName="SubCodigo" Header="Sub Código" Name="gridColumnSubCodigo" Width="100" />
                <dxg:GridColumn FieldName="Descricao" Header="Descrição do Produto" Name="gridColumnDescricao" Width="400" />
                <dxg:GridColumn FieldName="Quantidade" Header="Quantidade" HorizontalHeaderContentAlignment="Right" Name="gridColumnQuantidade" Width="100">
                    <dxg:GridColumn.EditSettings>
                        <dxg:LookUpEditSettings DisplayFormat="#,###" HorizontalContentAlignment="Right" />
                    </dxg:GridColumn.EditSettings>
                </dxg:GridColumn>
                <dxg:GridColumn FieldName="ValorTotal" Header="Valor Total" HorizontalHeaderContentAlignment="Right" Name="gridColumnValorTotal" Width="100">
                    <dxg:GridColumn.EditSettings>
                        <dxg:LookUpEditSettings DisplayFormat="c2" HorizontalContentAlignment="Right" />
                    </dxg:GridColumn.EditSettings>
                </dxg:GridColumn>
                <dxg:GridColumn FieldName="V1" Header="Código do Vendedor 1" Name="gridColumnV1" Visible="False" Width="35" />
                <dxg:GridColumn FieldName="NomeV1" Header="Nome do Vendedor1" Name="gridColumnNomeV1" Visible="False" Width="300" />
                <dxg:GridColumn FieldName="V2" Header="Código do Vendedor 2" Name="gridColumnV2" Visible="False" Width="35" />
                <dxg:GridColumn FieldName="NomeV2" Header="Nome do Vendedor2" Name="gridColumnNomeV2" Visible="False" Width="300" />
                <dxg:GridColumn FieldName="V3" Header="Código do Vendedor 3" Name="gridColumnV3" Visible="False" Width="35" />
                <dxg:GridColumn FieldName="NomeV3" Header="Nome do Vendedor3" Name="gridColumnNomeV3" Visible="False" Width="300" />
                <dxg:GridColumn FieldName="V4" Header="Código do Vendedor 4" Name="gridColumnV4" Visible="False" Width="35" />
                <dxg:GridColumn FieldName="NomeV4" Header="Nome do Vendedor4" Name="gridColumnNomeV4" Visible="False" Width="300" />
            </dxg:GridControl.Columns>

            <dxg:GridControl.GroupSummary>
                <dxg:GridSummaryItem DisplayFormat="Quantidade {0:#,###}" FieldName="Quantidade" ShowInColumn="Quantidade" SummaryType="Sum" />
                <dxg:GridSummaryItem DisplayFormat="Valor R${0:C2}" FieldName="ValorTotal" ShowInColumn="ValorTotal" SummaryType="Sum" />
            </dxg:GridControl.GroupSummary>

            <dxg:GridControl.TotalSummary>
                <dxg:GridSummaryItem DisplayFormat="Valor R${0:C2}" FieldName="ValorTotal" ShowInColumn="ValorTotal" SummaryType="Sum" />
                <dxg:GridSummaryItem DisplayFormat="Quantidade {0:#,###}" FieldName="Quantidade" ShowInColumn="Quantidade" SummaryType="Sum" />
            </dxg:GridControl.TotalSummary>

            <dxg:GridControl.Resources>
                <DataTemplate x:Key="CustomPrintHeaderTemplate">
                    <Grid>
                        <Rectangle RadiusX="5" RadiusY="5" Fill="Red" />
                        <dxe:TextEdit Text="Custom header template" IsPrintingMode="True" Width="{Binding Path=Content.(dxg:GridPrintingHelper.PrintRowInfo).TotalHeaderWidth}" FontSize="20"/>
                    </Grid>
                </DataTemplate>
            </dxg:GridControl.Resources>


            <dxg:GridControl.View>
                <dxg:TableView Name="tableView1" ShowGroupedColumns="False" ShowTotalSummary="True" />
            </dxg:GridControl.View>

        </dxg:GridControl>
    </Grid>
</UserControl>
I've confused things by pasting the wrong line of xaml.
My suggestion is to remove any specification of datacontext in the usercontrol definition -  it will pick up the existing data context at the point at which it is defined in the parent.

The attached code is WPF rather than Silverlight, but the principle is the same.
The Window has a Grid with DataContext set to a class TestViewModel.
The Grid contains two controls:
- a ComboBox with items bound to the 'Names' property and selected value bound to 'SelectedName'
- a UserControl ucTest

The UserControl contains a TextBlock bound to a 'SelectedName' property of whatever object instance is provided by the DataContext.
It picks-up the current DataContext from the Grid that contains it, therefore the name shown in the user control changes as the selection changes in the combo.
For a simple view model class (no Singleton pattern for example), specifying the DataContext in the user contol itself will create a new instance of the view model in which the SelectedName property has no connection with any change in selection in the combo

Hope this helps
Mike

<Window x:Class="UserControlBinding.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:UserControlBinding"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <local:TestViewModel x:Key="vm"/>
    </Window.Resources>
    <Grid DataContext="{StaticResource vm}" >
        <ListView ItemsSource="{Binding Names}" 
                  SelectedValue="{Binding SelectedName}"
                  VerticalAlignment="Top"/>
        <local:ucTest Margin="0,100" VerticalAlignment="Top"/>
    </Grid>
</Window>

<UserControl x:Class="UserControlBinding.ucTest"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <TextBlock Text="{Binding SelectedName}"/>
    </Grid>
</UserControl>

Open in new window