ShrShr
ShrShr

Reputation: 387

DataTemplate is not drawn, wpf

I have following code where I am trying to display a property of my data context. But I see nothing when I run the application. I am a beginner to WPF. I maybe missing some minor setting somewhere.

If I remove DataContext="{Binding RelativeSource={RelativeSource Self}}" and set the DataContext in code behind to MyPerson property and set

<ContentControl x:Name="myCC" Content="{Binding }"></ContentControl> then everything works good.

<Window x:Class="WpfTestApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          xmlns:local="clr-namespace:WpfTestApp"
        Title="MainWindow" Height="350" Width="525"
          DataContext="{Binding RelativeSource={RelativeSource Self}}">
    <Window.Resources>
        <DataTemplate DataType="{x:Type local:Person}">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"></RowDefinition>
                    <RowDefinition Height="Auto"></RowDefinition>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="200"></ColumnDefinition>
                    <ColumnDefinition Width="200"></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <Label Content="_Name:" Grid.Row="0" Grid.Column="0"></Label>
                <TextBox Text="{Binding Path=Name}" Grid.Column="1" Grid.Row="0"></TextBox>
                <Label Content="_Age:" Grid.Row="1" Grid.Column="0"></Label>
                <TextBox Text="{Binding Path=Age}" Grid.Column="1" Grid.Row="1"></TextBox>
            </Grid>
        </DataTemplate>
    </Window.Resources>
    <Grid >
        <ContentControl x:Name="myCC" Content="{Binding Path=MyPerson}"></ContentControl>
    </Grid>
</Window>


public partial class MainWindow : Window
    {
        public Person MyPerson { get; set; }
        public MainWindow()
        {
            InitializeComponent();
            MyPerson = new Person { Age = 30, Name = "David" };
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Button is clicked!!!");
        }       
    }



    public class Person : INotifyPropertyChanged
        {
            private int _age;
            private string _name;
            public int Age
            {
                get
                {
                    return _age;
                }
                set
                {
                    if (value != _age)
                    {
                        _age = value;
                        OnPropertyChanged("Age");
                    }
                }
            }
            public string Name
            {
                get
                {
                    return _name;
                }
                set
                {
                    if (value != _name)
                    {
                        _name = value;
                        OnPropertyChanged("Name");
                    }
                }

            }

            public event PropertyChangedEventHandler PropertyChanged;

            private void OnPropertyChanged(string propertyName)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }
        }

Upvotes: 0

Views: 98

Answers (2)

Abhinav Sharma
Abhinav Sharma

Reputation: 453

OFF Topic but a simple example using MVVM pattern

Your Model Class

public class Person : INotifyPropertyChanged
    {
        private int _age;
        private string _name;
        public int Age
        {
            get
            {
                return _age;
            }
            set
            {
                if (value != _age)
                {
                    _age = value;
                    OnPropertyChanged("Age");
                }
            }
        }
        public string Name
        {
            get
            {
                return _name;
            }
            set
            {
                if (value != _name)
                {
                    _name = value;
                    OnPropertyChanged("Name");
                }
            }

        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

ViewModel is a Wrapper around the Model

public class PersonViewModel : INotifyPropertyChanged
    {

       private Person myPerson;
       public Person MyPerson 
       { 
          get
             {
               if(myPerson == null)
                 myPerson=new Person { Age = 30, Name = "David" };
             }
          set
             {
               myPerson=value;
               OnPropertyChanged("MyPerson");
             }
       }
        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

View and ViewModel Binding

<Window x:Class="WpfTestApp.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:local="clr-namespace:WpfTestApp"
    Title="MainWindow" Height="350" Width="525">

<Window.DataContext>
   <local:PersonViewModel />
</Window.DataContext>

<Window.Resources>
    <DataTemplate DataType="{x:Type local:Person}">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"></RowDefinition>
                <RowDefinition Height="Auto"></RowDefinition>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="200"></ColumnDefinition>
                <ColumnDefinition Width="200"></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <Label Content="_Name:" Grid.Row="0" Grid.Column="0"></Label>
            <TextBox Text="{Binding Path=Name}" Grid.Column="1" Grid.Row="0"></TextBox>
            <Label Content="_Age:" Grid.Row="1" Grid.Column="0"></Label>
            <TextBox Text="{Binding Path=Age}" Grid.Column="1" Grid.Row="1"></TextBox>
        </Grid>
    </DataTemplate>
</Window.Resources>
<Grid >
    <ContentControl x:Name="myCC" Content="{Binding Path=MyPerson}"></ContentControl>
</Grid>

Hope this Helps!!!!

Upvotes: 0

dkozl
dkozl

Reputation: 33364

You create MyPerson after InitializeComponent, which also sets DataContext to MainWindow as specified in XAML, and since your property does not raise INotifyPropertyChanged.PropertyChanged event UI is never notified that it has changed. You can either implement INotifyPropertyChanged on MainWindow and raise PropertyChanged event for MyPerson property or if that property does not change, only its property changes, reverse the order

public MainWindow()
{
    MyPerson = new Person { Age = 30, Name = "David" };
    InitializeComponent();        
}

Upvotes: 1

Related Questions