I am beginner to WPF and I am facing problem while trying to bind a Dependency Property as the source of a CollectionViewSource.
The user control exposes a DependencyProperty of type List. It is used to present the data in a DataGrid with the help of CollectionViewSource (using it for Filtering, Grouping and Sorting operations).
My MainWindow XAML:
<Window>
<local:CustomUserControl x:Name="CustomUCDataGrid" ListToDisplay="{Binding listFromDB}"/>
<Window>
My MainWindow.cs:
public partial class MainWindow : Window
{
public List<customType> listFromDB{get;set;}
public MainWindow{
listFromDB = GetListFromDB();
InitializeComponent();
this.DataContext = this;
}
}
CustomUserControl.xaml looks something like:
<UserControl x:Name="ParentNode">
<DataGrid DataContext="{Binding ElementName=ParentNode}">
<StackPanel>
<DataGrid x:Name="DirectDataGrid" ItemSource="{Binding ListToDisplay}"/>
<DataGrid x:Name="DataGridWithCVS" ItemsSource="{Binding cvsList.View}"/>
</StackPanel>
</DataGrid>
</UserControl>
CustomUserControl.xaml.cs looks like:
public partial class CustomUserControl: UserControl
{
public List<customType> ListToDisplay{
get { return (List<customType>)GetValue(ListToDisplayProperty); }
set { SetValue(ListToDisplayProperty, value); }
}
public static readonly DependencyProperty ListToDisplayProperty=
DependencyProperty.Register("ListToDisplay", typeof(List<customType>),
typeof(CustomUserControl));
public CollectionViewSource cvsList { get; set; }
public CustomUserControl{
InitializeComponent();
cvsList = new CollectionViewSource();
cvsList.Source = ListToDisplay;
DataGridWithCVS.ItemsSource = CollectionViewSource.GetDefaultView(cvsList);
}
}
Here the DataGrid with name "DirectDataGrid" has no problem in displaying the data supplied to it from the MainWindow, but the DataGrid with name "DataGridWithCVS" doesn't display any data. Couldn't find any errors while debugging.
Things I have already Tried:
Define the CollectionViewSource as a StaticResource inside the CustomUserControl XAML - Can't implement this because, the UserControl doesn't use the DataContext set from the MainWindow. It uses its own DataContext without overriding the MainWindow's DataContext. (<UserControl x:Name="ParentNode"> <DataGrid DataContext="{Binding ElementName=ParentNode}">...).
It's just some kind of madness :)
Leave Code Behind alone.
In your case, apart from declaring DependecyProperty, there should be nothing there.
<UserControl x:Name="ParentNode">
<UserControl.Resources>
<CollectionViewSource x:Key="cvsList"
Source="{Binding ListToDisplay, ElementName=ParentNode}"/>
</UserControl.Resources>
<StackPanel>
<DataGrid x:Name="DirectDataGrid" ItemsSource="{Binding ListToDisplay, ElementName=ParentNode}"/>
<DataGrid x:Name="DataGridWithCVS" ItemsSource="{Binding Mode=OneWay, Source={StaticResource cvsList}}"/>
</StackPanel>
</UserControl>
I am building a WPF application with mahapps, prism[modularity]. I have below HomeWindow.xaml code.
<Controls:MetroWindow x:Class="Project.Views.HomeWindow"
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:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:local="clr-namespace:Project.Views"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
<!--The above code is for automatically binding of viewmodel into view-->
Height="700" Width="1200" Background="White">
<Grid>
<TabControl ItemsSource="{Binding TabCollection}">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock>
<TextBlock Text="{Binding Name}"/>
</TextBlock>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<Label Content="{Binding Content}" />
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
</Grid>
</Controls:MetroWindow>
I have below structure in my HomeViewModel.cs under ViewModels directory.
public class HomeViewModel : BindableBase
{
private ObservableCollection<Item> _tabCollection;
public ObservableCollection<Item> TabCollection { get { return _tabCollection; } set { SetProperty(ref _tabCollection, value); } }
//Prism way of getting and setting data
}
public class Item
{
private string Name;
private string Content;
public Item(string name, string content)
{
Name = name;
Content = content;
}
}
below is how I add data into TabCollection property through HomeWindow.xaml.cs.
private HomeViewModel _model=new HomeViewModel();
public HomeWindow(EmployeeViewModel model)
{
InitializeComponent();
_model.UserViewModel = model;
LoadHomeData(_model.UserViewModel.EmpRole);
DataContext = this;
}
private void LoadHomeData(string Role)
{
if (string.Equals(Role, "Admin"))
{
_model.TabCollection= new ObservableCollection<Item>()
{
new Item("Test1", "1"),
new Item("Test2", "2"),
new Item("Test3", "3")
};
}
}
Now matter what, the tabs will not get displayed. Its a blank empty window. I have followed the example in the issue here and have went through few similar posts having same kind of approach. But none of them helped. Is this because of prism way of databinding or is there anything else am missing here? Hope to find some help on this..
Your problem is not connected to MahApps or Prism but to how WPF works in general. In your case Name and Content are private fields and should be public properties
public string Name { get; set; }
public string Content { get; set; }
private or field is not a valid binding source. You can find more as to what is a valid binding source under Binding Sources Overview but in your case, as far as CLR object goes:
You can bind to public properties, sub-properties, as well as indexers, of any common language runtime (CLR) object. The binding engine uses CLR reflection to get the values of the properties. Alternatively, objects that implement ICustomTypeDescriptor or have a registered TypeDescriptionProvider also work with the binding engine.
Another problem is that DataContext is set wrong. At the moment is set to HomeWindow and I think it should be set to instance of HomeViewModel which holds TabCollection property
DataContext = _model;
In my solution; I have two projects: One is a WPF UserControl Library, and the other is a WPF Application.
The usercontrol is pretty straightforward; it's a label and a combo box that will show the installed printers.
In the WPF application; I want to use this usercontrol. The selected value will be stored in user settings.
The problem I'm having is that I can't seem to get the proper binding to work. What I need to happen is to be able to set the SelectedValue of the UserControl when the MainWindow loads; as well as access the SelectedValue of the UserControl when I go to save my settings.
My code is below, could someone point me in the right direction?
PrintQueue user control:
<UserControl x:Class="WpfControls.PrintQueue"
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" xmlns:wpfControls="clr-namespace:WpfControls"
mc:Ignorable="d">
<UserControl.DataContext>
<wpfControls:PrintQueueViewModel/>
</UserControl.DataContext>
<Grid>
<StackPanel Orientation="Horizontal">
<Label Content="Selected Printer:"></Label>
<ComboBox ItemsSource="{Binding Path=PrintQueues, Mode=OneWay}" DisplayMemberPath="Name" SelectedValuePath="Name" Width="200" SelectedValue="{Binding Path=SelectedPrinterName, Mode=TwoWay}"></ComboBox>
</StackPanel>
</Grid>
</UserControl>
Print Queue Codebehind:
public partial class PrintQueue : UserControl
{
public static readonly DependencyProperty CurrentPrinterNameProperty =
DependencyProperty.Register("CurrentPrinterName", typeof (string), typeof (PrintQueue), new PropertyMetadata(default(string)));
public string CurrentPrinterName
{
get { return (DataContext as PrintQueueViewModel).SelectedPrinterName; }
set { (DataContext as PrintQueueViewModel).SelectedPrinterName = value; }
}
public PrintQueue()
{
InitializeComponent();
DataContext = new PrintQueueViewModel();
}
}
PrintQueue View Model:
public class PrintQueueViewModel : ViewModelBase
{
private ObservableCollection<System.Printing.PrintQueue> printQueues;
public ObservableCollection<System.Printing.PrintQueue> PrintQueues
{
get { return printQueues; }
set
{
printQueues = value;
NotifyPropertyChanged(() => PrintQueues);
}
}
private string selectedPrinterName;
public string SelectedPrinterName
{
get { return selectedPrinterName; }
set
{
selectedPrinterName = value;
NotifyPropertyChanged(() => SelectedPrinterName);
}
}
public PrintQueueViewModel()
{
PrintQueues = GetPrintQueues();
}
private static ObservableCollection<System.Printing.PrintQueue> GetPrintQueues()
{
var ps = new PrintServer();
return new ObservableCollection<System.Printing.PrintQueue>(ps.GetPrintQueues(new[]
{
EnumeratedPrintQueueTypes.Local,
EnumeratedPrintQueueTypes.Connections
}));
}
}
Main Window:
<Window x:Class="WPFApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wpfControls="clr-namespace:WpfControls;assembly=WpfControls" xmlns:wpfApp="clr-namespace:WPFApp"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<wpfApp:MainWindowViewModel/>
</Window.DataContext>
<Grid>
<StackPanel>
<wpfControls:PrintQueue CurrentPrinterName="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.PrinterName, Mode=TwoWay}"></wpfControls:PrintQueue>
</StackPanel>
</Grid>
</Window>
Main Window View Model:
public class MainWindowViewModel : ViewModelBase
{
private string printerName;
public string PrinterName
{
get { return printerName; }
set
{
printerName = value;
NotifyPropertyChanged(() => PrinterName);
}
}
public MainWindowViewModel()
{
PrinterName = "Lexmark T656 PS3";
}
}
Controls in a library need to expose DependencyProperties that you can bind to in your view. Just like WPF's TextBox exposes a Text property.
Your PrintQueue control doesn't expose anything, and instead keeps all its state in a viewmodel that nothing outside can access. Your MainWindowViewModel has no way of getting at the stuff inside PrintQueueViewModel.
You need to expose SelectedPrinterName as a DependencyProperty in the code behind of your PrintQueue xaml. Then in MainWindow.xaml you can bind it to MainWindowViewModel.PrinterName.
If you want to user ViewModels all the way through instead, then MainWindowViewModel should be creating PrintQueueViewModel itself so it can access the properties within.
As per your update / comment:
Unfortunately DependencyProperties don't work like that. The getters/setters aren't even used most of the time, and they should ONLY update the property itself. You're sort of halfway between two worlds at the moment.
If I were in your position, and assuming you can change the library so PrintQueue.xaml doesn't have a hardcoded VM instance in the view, I would just create the PrintQueueViewModel yourself. That's how MVVM is supposed to work:
ViewModel:
public class MainWindowViewModel : ViewModelBase
{
public PrintQueueViewModel PrintQueue { get; private set; }
public MainWindowViewModel()
{
PrintQueue = new PrintQueueViewModel();
PrintQueue.SelectedPrinterName = "Lexmark T656 PS3";
}
}
View:
<Window x:Class="WPFApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wpfControls="clr-namespace:WpfControls;assembly=WpfControls" xmlns:wpfApp="clr-namespace:WPFApp"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<wpfApp:MainWindowViewModel/>
</Window.DataContext>
<Grid>
<StackPanel>
<wpfControls:PrintQueue DataContext="{Binding PrintQueue}"/>
</StackPanel>
</Grid>
</Window>
Again though, control libraries generally don't have view models, and expose their state via dependency properties since they're designed to be used in XAML.
Component libraries may expose view models, but in that case they wouldn't hard code the view model in the view.
Did you write the library? If not, how did the author expect people to use it?
I think with this small changes everything should work
<ComboBox ItemsSource="{Binding Path=PrintQueues, Mode=OneWay}" DisplayMemberPath="Name" Width="200" SelectedItem="{Binding Path=SelectedPrinter, Mode=TwoWay}"></ComboBox>
private System.Printing.PrintQueue selectedPrinter;
public System.Printing.PrintQueue SelectedPrinter
{
get { return selectedPrinter; }
set
{
selectedPrinter = value;
NotifyPropertyChanged(() => SelectedPrinter);
}
}
Now from the main window you can modify SelectedPrinter on the viewmodel and the change should be reflected on the view
(PrintQueue.DataContext as PrintQueueViewModel).SelectedPrinter = ...
I tried your code and your bindings of the PrintQueueView to the corresponding view model work fine. Your problem is that the MainWindowViewModel does not know about the PrintQueueViewModel and thus cannot retrieve the value of the selected printer when the main window closes (I guess that is the scenario you want to implement).
The quickest solution to your problem would be to do the following steps:
In MainWindow.xaml, give PrintQueue a Name so you can access it in the code behind
In MainWindow.xaml.cs, override the OnClosing method. In it you can retrieve the view model as follows: var viewModel = (PrintQueueViewModel)PrintQueue.DataContext;. After that you can retrieve the selected value and save it or whatever.
In the MainWindow constructor after InitializeComponent, you can retrieve your saved value from a file and set it on the PrintQueueViewModel by retrieving it the same way as in the previous step.
Whole code in MainWindow.xaml.cs:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// Retrieve your selected printer here; in this case, I just set it directly
var selectedPrinter = "Lexmark T656 PS3";
var viewModel = (PrintQueueViewModel)PrintQueue.DataContext;
viewModel.SelectedPrinterName = selectedPrinter;
}
protected override void OnClosing(CancelEventArgs e)
{
var viewModel = (PrintQueueViewModel)PrintQueue.DataContext;
var selectedPrinterName = viewModel.SelectedPrinterName;
// Save the name of the selected printer here
base.OnClosing(e);
}
}
Please remember that the major point of view models is the ability to unit-test GUI logic and to disconnect GUI appearance and logic. Your view models should not be able to retrieve all the possible printers of your system but should obtain these values by e.g. Dependency Injection. I would advise you to read about SOLID programming.
Question: Can anyone please provide a full code example that shows how one does programmatically change the SelectedItem of a data-bound WPF ComboBox without using MyComboBox.SelectedIndex?
Code sample: Here is what I currently have.
XAML:
<Window x:Class="Wpf.ComboBoxDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ComboBox Name="MyComboBox" DisplayMemberPath="LastName" SelectedIndex="0"/>
</Grid>
</Window>
Code-behind:
using System.Collections.ObjectModel;
using System.Windows;
namespace Wpf.ComboBoxDemo
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
ObservableCollection<Person> myPersonList = new ObservableCollection<Person>();
Person personJobs = new Person("Steve", "Jobs");
Person personGates = new Person("Bill", "Gates");
myPersonList.Add(personJobs);
myPersonList.Add(personGates);
MyComboBox.ItemsSource = myPersonList;
// How do I programmatically select the second Person, i.e. "Gates"?
// The best pratice must be to somehow to set something like IsCurrentlySelected on the model, so the view update automatically. But how?
MyComboBox.SelectedIndex = 1; // This works, but is there no way without using the index?
}
private class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public Person(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
}
}
}
Similar questions: I have of course searched the Internet first, but found nothing that helped me.
Changing the SelectedItem of a enum-bound combobox inside ViewModel (MSDN)
Programmatically set ComboBox SelectedItem in WPF (3.5sp1) (Stack Overflow)
At the top of my head (I might be wrong), make the window implement INotifyPropertyChanged and add the event:
namespace Wpf.ComboBoxDemo
{
public partial class MainWindow : Window, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public MainWindow()
{
Then add a property for the currently selected item which notifies on changes:
private Person _selected;
public Person MySelected
{
get { return _selected; }
set
{
if (value != _selected)
{
_selected = value;
if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs("MySelected"));
}
}
}
}
Now bind the combobox (the binding could be more advanced here using FindAncestor but sometimes to keep things simple I put the datacontext in code behind):
XAML:
<ComboBox
Name="MyComboBox"
DisplayMemberPath="LastName"
SelectedItem="{Binding MySelected}" />
Code behind:
public MainWindow()
{
InitializeComponent();
// ...
// this will cause the "MySelected" binding to target the correct property on this object
MyComboBox.DataContext = this;
}
I think it goes something like that. I cant test it right now but hopefully it will nudge you in the right direction.
Edit: If you want to try the "other way" of binding heres how. Expand the SelectedItem binding to look like this:
<ComboBox
Name="MyComboBox"
DisplayMemberPath="LastName"
SelectedItem="{Binding MySelected,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Window}}}" />
You can now skip setting the DataContext in code behind:
public MainWindow()
{
InitializeComponent();
// ...
// this will cause the "MySelected" binding to target the correct property on this object
//MyComboBox.DataContext = this;
}
This is because that FindAncestor mode makes the ComboBox itself find the object to which property it should bind, rather than you specifically stating.
The current hot topic here at the office is which of these two ways are the best. To me its just more XAML and less code behind (or the other way around), just use the method that places the code where youre comfortable to work. I think there are some scenarios where the latter is preferred (like when you include data binding controls inside other controls), but Im just dabbling so I havent really figured those parts out yet.
I have some object that is instantiated in code behind, for instance, the XAML is called window.xaml and within the window.xaml.cs
protected Dictionary<string, myClass> myDictionary;
How can I bind this object to, for example, a list view, using only XAML markups?
Update:
(This is exactly I have in my test code):
<Window x:Class="QuizBee.Host.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="{Binding windowname}" Height="300" Width="300"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
</Grid>
</Window>
And in codebehind
public partial class Window1 : Window
{
public const string windowname = "ABCDEFG";
public Window1()
{
InitializeComponent();
}
}
Suppose the title should become "ABCDEFG" right? but it ends up showing nothing.
There's a much easier way of doing this. You can assign a Name to your Window or UserControl, and then binding by ElementName.
Window1.xaml
<Window x:Class="QuizBee.Host.Window1"
x:Name="Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ListView ItemsSource="{Binding ElementName=Window1, Path=myDictionary}" />
</Window>
Window1.xaml.cs
public partial class Window1:Window
{
// the property must be public, and it must have a getter & setter
public Dictionary<string, myClass> myDictionary { get; set; }
public Window1()
{
// define the dictionary items in the constructor
// do the defining BEFORE the InitializeComponent();
myDictionary = new Dictionary<string, myClass>()
{
{"item 1", new myClass(1)},
{"item 2", new myClass(2)},
{"item 3", new myClass(3)},
{"item 4", new myClass(4)},
{"item 5", new myClass(5)},
};
InitializeComponent();
}
}
You can set the DataContext for your control, form, etc. like so:
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Clarification:
The data context being set to the value above should be done at whatever element "owns" the code behind -- so for a Window, you should set it in the Window declaration.
I have your example working with this code:
<Window x:Class="MyClass"
Title="{Binding windowname}"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Height="470" Width="626">
The DataContext set at this level then is inherited by any element in the window (unless you explicitly change it for a child element), so after setting the DataContext for the Window you should be able to just do straight binding to CodeBehind properties from any control on the window.
While Guy's answer is correct (and probably fits 9 out of 10 cases), it's worth noting that if you are attempting to do this from a control that already has its DataContext set further up the stack, you'll resetting this when you set DataContext back to itself:
DataContext="{Binding RelativeSource={RelativeSource Self}}"
This will of course then break your existing bindings.
If this is the case, you should set the RelativeSource on the control you are trying to bind, rather than its parent.
i.e. for binding to a UserControl's properties:
Binding Path=PropertyName,
RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}
Given how difficult it can be currently to see what's going on with data binding, it's worth bearing this in mind even if you find that setting RelativeSource={RelativeSource Self} currently works :)
Just a little more clarification: A property without 'get','set' won't be able to be bound
I'm facing the case just like the asker's case. And I must have the following things in order for the bind to work properly:
//(1) Declare a property with 'get','set' in code behind
public partial class my_class:Window {
public String My_Property { get; set; }
...
//(2) Initialise the property in constructor of code behind
public partial class my_class:Window {
...
public my_class() {
My_Property = "my-string-value";
InitializeComponent();
}
//(3) Set data context in window xaml and specify a binding
<Window ...
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<TextBlock Text="{Binding My_Property}"/>
</Window>
In your code behind, set the window's DataContext to the dictionary. In your XAML, you can write:
<ListView ItemsSource="{Binding}" />
This will bind the ListView to the dictionary.
For more complex scenarios, this would be a subset of techniques behind the MVVM pattern.
One way would be to create an ObservableCollection (System.Collections.ObjectModel) and have your dictionary data in there. Then you should be able to bind the ObservableCollection to your ListBox.
In your XAML you should have something like this:
<ListBox ItemsSource="{Binding Path=Name_of_your_ObservableCollection" />
Define a converter:
public class RowIndexConverter : IValueConverter
{
public object Convert( object value, Type targetType,
object parameter, CultureInfo culture )
{
var row = (IDictionary<string, object>) value;
var key = (string) parameter;
return row.Keys.Contains( key ) ? row[ key ] : null;
}
public object ConvertBack( object value, Type targetType,
object parameter, CultureInfo culture )
{
throw new NotImplementedException( );
}
}
Bind to a custom definition of a Dictionary. There's lot of overrides that I've omitted, but the indexer is the important one, because it emits the property changed event when the value is changed. This is required for source to target binding.
public class BindableRow : INotifyPropertyChanged, IDictionary<string, object>
{
private Dictionary<string, object> _data = new Dictionary<string, object>( );
public object Dummy // Provides a dummy property for the column to bind to
{
get
{
return this;
}
set
{
var o = value;
}
}
public object this[ string index ]
{
get
{
return _data[ index ];
}
set
{
_data[ index ] = value;
InvokePropertyChanged( new PropertyChangedEventArgs( "Dummy" ) ); // Trigger update
}
}
}
In your .xaml file use this converter. First reference it:
<UserControl.Resources>
<ViewModelHelpers:RowIndexConverter x:Key="RowIndexConverter"/>
</UserControl.Resources>
Then, for instance, if your dictionary has an entry where the key is "Name", then to bind to it: use
<TextBlock Text="{Binding Dummy, Converter={StaticResource RowIndexConverter}, ConverterParameter=Name}">
Make your property "windowname" a DependencyProperty and keep the remaining same.
I was having this exact same problem but mine wasn't because I was setting a local variable... I was in a child window, and I needed to set a relative DataContext which I just added to the Window XAML.
<Window x:Class="Log4Net_Viewer.LogItemWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="LogItemWindow" Height="397" Width="572">
You can try x:Reference trick
<Window ... x:Name="myWindow"><ListBox ItemsSource="{Binding Items, Source={x:Reference myWindow}}" /></Window>
That's my way to bind to code behind (see property DataTemplateSelector)
public partial class MainWindow : Window
{
public MainWindow()
{
this.DataTemplateSelector = new MyDataTemplateSelector();
InitializeComponent();
// ... more initializations ...
}
public DataTemplateSelector DataTemplateSelector { get; }
// ... more code stuff ...
}
In XAML will referenced by RelativeSource via Ancestors up to containing Window, so I'm at my Window class and use the property via Path declaration:
<GridViewColumn Header="Value(s)"
CellTemplateSelector="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataTemplateSelector}"/>
Setting of property DataTemplateSelector before call InitializeComponent depends on missing implementation of IPropertyChanged or use of implementation with DependencyProperty so no communication run on change of property DataTemplateSelector.