4

I cannot understand why my DataContext binding doesn't work when I run my app. I am also using design-time datacontext and it works.

Here are the main parts from my XAML. This is from MainWindow.xaml

<Window x:Class="Logs_Cleaner_WPF.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="600" Width="800" MinWidth="800" MinHeight="600" WindowStartupLocation="CenterScreen"
    xmlns:data="clr-namespace:Logs_Cleaner_WPF.Data"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    DataContext="{Binding Items, RelativeSource={RelativeSource Self}}"
    d:DataContext="{Binding Source={d:DesignInstance Type=data:DesignData, IsDesignTimeCreatable=True}}"
    mc:Ignorable="d">

This is also from MainWindow.xaml

<Window.Resources>
    <HierarchicalDataTemplate x:Key="ChildDataTemplate">
        <TextBlock Text="{Binding Path}"></TextBlock>
    </HierarchicalDataTemplate>
    <HierarchicalDataTemplate x:Key="RootDataTemplate" ItemsSource="{Binding DisplayFolders}" ItemTemplate="{StaticResource ChildDataTemplate}">
        <TextBlock Text="{Binding Path}"></TextBlock>
    </HierarchicalDataTemplate>
</Window.Resources>

This is the main TreeView. I need to display everything here.

<TreeView DataContext="{Binding}" ItemsSource="{Binding Items}"     x:Name="TreeView" Grid.Row="1" VerticalContentAlignment="Top" Margin="10,5" ItemTemplate="{StaticResource RootDataTemplate}">
    </TreeView>

And here is C# code. This is from MainWindow.xaml.cs, namespace is Logs_Cleaner_WPF

public partial class MainWindow : Window
{
    public static ObservableCollection<DisplayItem> Items { get; set; }
}

DisplayItem:

public abstract class DisplayItem : INotifyPropertyChanged
{
    private string _path;
    public virtual string Path
    {
        get { return _path; }
        set
        {
            _path = value;
            OnPropertyChanged();
        }
    }

    private long _size;
    public long Size {
        get { return _size; }
        set
        {
            _size = value;
            OnPropertyChanged();
        } 
    }

    private bool _checked;
    public bool Checked
    {
        get { return _checked; }
        set
        {
            _checked = value;
            OnPropertyChanged();
        }
    }

    public override string ToString()
    {
        return Path;
    }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}
Maksym
  • 37
  • 2
  • How do you populate your Items collection with the data ? – Maxim Fleitling Jan 06 '16 at 14:48
  • private void OnLoaded(object sender, RoutedEventArgs routedEventArgs) { _dirHelper = App.UnityContainer.Resolve(); JustForTest(); } private void JustForTest() { Items = new ObservableCollection(); Items.Add(new DisplayFolder { Checked = true, Path = "MyPath7" }); } – Maksym Jan 06 '16 at 14:55
  • You might find [this answer about the DataContext](http://stackoverflow.com/a/7262322/302677) useful to read through :) – Rachel Jan 06 '16 at 15:01
  • Please don't put code in a comment, instead edit your question and include the code there. – Chris Dunaway Jan 06 '16 at 15:01

2 Answers2

2

Because of the declaration before, your DataContext is already Items collection!

DataContext="{Binding Items, RelativeSource={RelativeSource Self}}"

So binding to ItemsSource should just be {Binding }

<TreeView ItemsSource="{Binding }" x:Name="TreeView" ... />

In your case it's {Binding Items} again, so it's trying to bind to Items.Items, which does not exist.

Rachel
  • 130,264
  • 66
  • 304
  • 490
Maxim Fleitling
  • 542
  • 4
  • 14
  • I changed TreeView ItemsSource="{Binding}" but it is still the same problem. design dataContext works but if I ran the program - it doesn't show me anything, though the Items collection is not empty. – Maksym Jan 06 '16 at 15:03
  • 1
    @Maksym This is the correct answer, although it should be noted that you'll also have to change your design time data structure or the binding for it if you go this route. An alternative would be to alter the `Window.DataContext` binding to leave out the "Items", so it sets the DataContext to the Window object itself, and does not set it to the `Window.Items` property. `DataContext="{Binding RelativeSource={RelativeSource Self}}"` – Rachel Jan 06 '16 at 15:05
  • @Rachel The correct answer is probably to follow MVVM and create an actual view model for the collection, then set the DataContext of Window appropriately, and probably to use HierarchicalDataTemplates correctly. – Kcvin Jan 06 '16 at 15:12
-2

I think it is better to rewrite it in an appropriate way, as @NETscape suggested. I'm going to implement MVVM.

Maksym
  • 37
  • 2
  • 2
    I applaud you for your decision to follow MVVM, but this isn't really an answer. Figure out which of the answers that have been posted worked for you in regards to the original question asked, mark it according, and delete this (your) answer; or delete this question in its entirety. – Kcvin Jan 06 '16 at 15:19
  • 1
    We are happy to help anyone learning MVVM in the [WPF chat room](http://chat.stackoverflow.com/rooms/18165/wpf) – Kcvin Jan 06 '16 at 15:20