none
DataBinding in DataTemplates RRS feed

  • Frage

  • Hi,

    i have build a small sample where i use a datatemplate in my own usercontrol. What i now need is databinding in a template. Can anybody help me?
    (This thread continues this one: http://social.msdn.microsoft.com/Forums/de-DE/wpf/thread/a0e25df9-f74f-4c8f-a9d2-03ea2529068e so thats the reason why this is in english too)

    small class Person:

    public class Person
    {
        public bool IsSingle { get; set; }
    public string Name { get; set; }

     

     

    }

    small usercontrol

    public partial class PersonControl : UserControl
    {
        public PersonControl()
        {
            InitializeComponent();
        }
    
        private Person person;
        public Person Person
        {
            get { return person; }
            set
            {
                person = value;
                this.ContentTemplate = this.ContentTemplateSelector.SelectTemplate(value, this);
            }
        }
    }
    
    <UserControl x:Class="UserTemplateTest.PersonControl"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:local="clr-namespace:UserTemplateTest"
        Height="300" Width="300" >
        <UserControl.Resources>
            <DataTemplate x:Key="SinglePerson" >
                <TextBlock FontSize="20"  Width="200.098" Height="30.255" Text="{Binding Name}" />
            </DataTemplate >
    
            <DataTemplate  x:Key="NonSinglePerson" >
                <TextBlock FontSize="20"  Width="200.098" Height="30.255" Text="{Binding Name}" />
            </DataTemplate >
        </UserControl.Resources>
        <UserControl.ContentTemplateSelector>
            <local:PersonSelector />
        </UserControl.ContentTemplateSelector>
    </UserControl>

    small TemplateSelector

    class PersonSelector : DataTemplateSelector
    {
    
        public override System.Windows.DataTemplate SelectTemplate(object item, System.Windows.DependencyObject container)
        {
            Person person = item as Person;
            string templateKey = "SinglePerson";
            UserControl userControl = container as UserControl;
    
            if (person == null || userControl == null)
            {
                return base.SelectTemplate(item, container);
            }
    
            // Die hier benutzten Templates sind in XAML definiert
            if (person.IsSingle)
                templateKey = "SinglePerson";
            else
                templateKey = "NonSinglePerson";
            return userControl.FindResource(templateKey) as DataTemplate;
        }
    }
    


    small Window

    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }
    
        private void btn_single_Click(object sender, RoutedEventArgs e)
        {
            Person p = new Person { IsSingle = true, Name = "SinglePerson" };
            personControl1.Person = p;
        }
    
        private void btn_nonSingle_Click(object sender, RoutedEventArgs e)
        {
            Person p = new Person { IsSingle = false, Name = "NonSinglePerson" };
            personControl1.Person = p;
        }
    }
    
    <Window x:Class="UserTemplateTest.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:UserTemplateTest"
        Title="Window1" Height="445" Width="446">
        <Grid>
            <local:PersonControl x:Name="personControl1" DataContext="{Binding Person}"  Margin="43,46,85,66"></local:PersonControl>
            <Button Height="30" HorizontalAlignment="Left" Margin="27,9,0,0" Name="btn_single" VerticalAlignment="Top" Width="128" Click="btn_single_Click">SetSingle</Button>
            <Button Height="32" Margin="190,9,73,0" Name="btn_nonSingle" VerticalAlignment="Top" Click="btn_nonSingle_Click">SetNonSingle</Button>
        </Grid>
    </Window>
    


    VB.NET & C#.NET
    Mittwoch, 6. Januar 2010 10:02

Antworten

  • Hallo Nico,

    du machst es dir künstlich schwer. Verwende doch den DataContext von deinem UserControl anstelle des Person Property. Wenn sich der DataContext (Person) ändert wird mit dem DataTemplateSelector das dazu passende DataTemplate selektiert.
    Mittwoch, 6. Januar 2010 12:32
  • also es geht, wenn man folgendes hinzufügt:

    <UserControl x:Class="UserTemplateTest.PersonControl" ... Name="uctrl">

    ...
          <DataTemplate ...>
                 <TextBlock ....... Text="{Binding DataContext.Name, ElementName=uctrl}" />
          </DataTemplate >
    ...
    </UserControl>

    und im PersonSelector fügt man nur noch hinzu:
    userControl.DataContext = person;

    Und so kann man auch wirklich unterscheiden, in welchen Situationen welcher DataContext gesetzt wird... Also so hab ich das nun bei mir gelöst... Oder gibt es da noch eine bessere Variante??
    VB.NET & C#.NET
    Mittwoch, 6. Januar 2010 13:06

Alle Antworten

  • Hallo Nico,

    du machst es dir künstlich schwer. Verwende doch den DataContext von deinem UserControl anstelle des Person Property. Wenn sich der DataContext (Person) ändert wird mit dem DataTemplateSelector das dazu passende DataTemplate selektiert.
    Mittwoch, 6. Januar 2010 12:32
  • set
    {
    	person = value;				
    	this.ContentTemplate = this.ContentTemplateSelector.SelectTemplate(value, this);
    	this.Content = value;
    }

    Du hast vergessen den Content zu setzen, darum wird nichts angezeigt. Bei diesem Code stellen sich mir aber die Nackenhaare auf.



    Mittwoch, 6. Januar 2010 13:06
  • also es geht, wenn man folgendes hinzufügt:

    <UserControl x:Class="UserTemplateTest.PersonControl" ... Name="uctrl">

    ...
          <DataTemplate ...>
                 <TextBlock ....... Text="{Binding DataContext.Name, ElementName=uctrl}" />
          </DataTemplate >
    ...
    </UserControl>

    und im PersonSelector fügt man nur noch hinzu:
    userControl.DataContext = person;

    Und so kann man auch wirklich unterscheiden, in welchen Situationen welcher DataContext gesetzt wird... Also so hab ich das nun bei mir gelöst... Oder gibt es da noch eine bessere Variante??
    VB.NET & C#.NET
    Mittwoch, 6. Januar 2010 13:06
  • Warte. Mir gefällt deine Lösung gar nicht. Du vermengst den DataTemplateSelector mit dem UserControl.

    Die Aufgabe die dir gestellt hast war:

    Handelt es sich um einen Single stelle ich ihn mit DataTemplate1 dar.
    Handelt um ein Paar verwende ich DataTemplate2.

    Dazu brauchen wir nicht mal ein UserControl. Ich mach mal ein Beispiel fertig das dir zeigt wie ich es machen würde.


    Mittwoch, 6. Januar 2010 13:29
  • Hat ein wenig gedauert, musste noch schnell ein Sudoko gegen meine Frau verlieren.

    Hier meine Art dein Problem zu lösen, es gibt sicher noch viele weitere Lösungen.

    <Window

          x:Class="WpfApplication1.Window44"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"      

          xmlns:local="clr-namespace:WpfApplication1"

        Title="Window44" Height="300" Width="300"

          >

         

          <Window.Resources>

                <DataTemplate x:Key="SinglePerson" >

                      <TextBlock FontSize="20"  Width="200" Height="30" Text="{Binding Name}" />

                </DataTemplate >

     

                <DataTemplate  x:Key="NonSinglePerson" >

                      <TextBlock FontSize="20"  Width="200" Height="30" Text="{Binding Name}" />

                </DataTemplate >

     

                <local:PersonDataTemplateSelector

                      x:Key="_dataTemplateSelector"                                                           

                      SingleDataTemplate="{StaticResource SinglePerson}"

                      NonSingleDataTemplate="{StaticResource NonSinglePerson}"

                      />

          </Window.Resources>

         

          <StackPanel>

                <Button

                      Name="btn_single"

                      Click="btn_single_Click"

                      Content="SetSingle"

                      />

               

                <Button                

                      Name="btn_nonSingle"

                      Click="btn_nonSingle_Click"

                      Content="SetNonSingle"

                      />

               

                <ContentControl

                      ContentTemplateSelector="{StaticResource _dataTemplateSelector}"

                      Content="{Binding}"

                      />   

          </StackPanel>

         

    </Window>

     

    public partial class Window44 : Window

    {

          public Window44()

          {

                InitializeComponent();

          }

     

          private void btn_single_Click(object sender, RoutedEventArgs e)

          {                

                this.DataContext = new Person { IsSingle = true, Name = "SinglePerson" };

          }

     

          private void btn_nonSingle_Click(object sender, RoutedEventArgs e)

          {                

                this.DataContext = new Person { IsSingle = false, Name = "NonSinglePerson" };

          }

    }

     

    public class Person

    {

          public bool IsSingle { get; set; }    public string Name { get; set; }

    }

     

    public class PersonDataTemplateSelector : DataTemplateSelector

    {

          public DataTemplate NonSingleDataTemplate { get; set; }

          public DataTemplate SingleDataTemplate { get; set; }

     

          public override System.Windows.DataTemplate SelectTemplate(object item, System.Windows.DependencyObject container)

          {

                Person person = item as Person;

     

                if (person == null)                     

                      return base.SelectTemplate(item, container);

     

                return person.IsSingle ? this.SingleDataTemplate : this.NonSingleDataTemplate;                 

          }

    }


    Auf diese Weise kannst du den PersonDataTemplateSelector auch für eine ListBox oder ein anderes Control verwenden.

    Hope that helps
    Mittwoch, 6. Januar 2010 14:40