user1133555
user1133555

Reputation: 103

WPF DataContext inheritance from MainWindow to UserControl

I am a newbie in WPF, I have a problem concern DataContext inheritance from the MainWindow to a UserControl, which will be attached as a Tabpage to the MainWindow's Tabcontrol.

My code snippets are as follows:

UserControlModel.cs

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

        // Create the OnPropertyChanged method to raise the event
        protected void OnPropertyChanged(string name)
        {
            var handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion
    }

ViewModelLocator.cs

    public class ViewModelLocator
    {
        private UserControlModel UserControlModel { get; set; }

        public ObservableCollection<UserControlModel> Users { get; set; }

        public ViewModelLocator()
        {
            Users = new ObservableCollection<UserControlModel>
            {
                new UserControlModel { Name = "Albert" },
                new UserControlModel { Name = "Brian" }
            };
        }
    }

MainWindow.xaml

<Window.Resources>
    <local:ViewModelLocator x:Key="VMLocator" />
</Window.Resources>

<Grid HorizontalAlignment="Left" Height="330" VerticalAlignment="Top" Width="592">
    <Grid HorizontalAlignment="Left" Height="45" Margin="0,330,-1,-45" VerticalAlignment="Top" Width="593">
        <Button Content="Button" HorizontalAlignment="Left" Margin="490,5,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
    </Grid>
    <TabControl HorizontalAlignment="Left" Height="330" VerticalAlignment="Top" Width="592" >
        <TabItem x:Name="UserControlTabItem" Header="User Control">
            <Grid x:Name="UserControlTabpage" Background="#FFE5E5E5">
                <local:UserControl VerticalAlignment="Top" DataContext="{Binding Users, Source={StaticResource VMLocator}}" />
            </Grid>
        </TabItem>
    </TabControl>
</Grid>

I create an instance of ViewModelLocator and bind Users instance to the UserControl in MainWindow.xaml.

MainWindow.xaml.cs

        public MainWindow()
        {
            InitializeComponent();
        }

UserControl.xaml

<Grid>
    <ListBox x:Name="lbUsers" DisplayMemberPath="???" HorizontalAlignment="Left" Height="250" Margin="30,27,0,0" VerticalAlignment="Top" Width="378"/>
</Grid>

UserControl.xaml.cs

        private ObservableCollection<UserControlModel> _users;

        public UserControl()
        {
            InitializeComponent();
            
            _users = ???;// How to reference the Users instance created in MainWindow ???

            lbUsers.ItemsSource = _users;
        }

Actually, I want to show the Name property of UserControlModel in the ListBox. If I am right, UserControl instance is inherited with a Users instance as the DataContext from MainWindow. How can I reference the Users instance in the code-behind of UserControl.xaml.cs?

I have checked that DataContext in UserControl constructor is null! How come? What is the correct way/place to test the DataContext in the code-behind? Also, how to set DisplayMemberPath attribute of the ListBox in UserControl.xaml. Many thanks.

Upvotes: 1

Views: 1009

Answers (2)

mm8
mm8

Reputation: 169150

You need to bind the ItemsSource property of the ListBox to the source collection. Since the DataContext of the UserControl is a ObservableCollection<UserControlModel>, you can bind to it directly:

<ListBox x:Name="lbUsers" ItemsSource="{Binding}" DisplayMemberPath="Name" ... />

Also make sure that you don't explicitly set the DataContext of the UserControl anywhere else in your code.

Although you should be able to reference the DataContext once the UserControl has been loaded:

public UserControl()
{
    InitializeComponent();
    this.Loaded += (s, e) =>
    {
        _users = DataContext as ObservableCollection<UserControlModel>;
    };
}

...there is no need to set the ItemsSource property of the ListBox in the code-behind. You should do this by creating a binding in the XAML.

Upvotes: 0

VipinKV
VipinKV

Reputation: 66

I think you can set or inherit DataContext in XAML of user control like this

UserControl.xaml

<dialogs:Usercontrol DataContext="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext}" />

Upvotes: 1

Related Questions