I've been playing around with WPF for the first time, specifically using a ListView that I want to bind to a ObservableCollection that is a property on the code-behind page. Right now I'm just trying to get a feel for how things work so I've tried keeping this simple. Unfortunately I don't quite see where I'm going wrong with this.
My code-behind page has a property that looks like this:
public ObservableCollection<Code> Code { get; set; }
I have a button on the form that queries and populates the Code property.
The Code class is a simple POCO class:
public class Code
{
public string Line { get; set; }
}
I have added a namespace to the XAML window:
<Window x:Class="SampleWPF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SampleWPF"
Title="MainWindow" Height="350" Width="525"
>
And the ListView looks like this:
<DockPanel Height="311" HorizontalAlignment="Left" Name="dockPanel1"
VerticalAlignment="Top" Width="182">
<ListView Name="lstCode"
ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Window, AncestorLevel=1}, Path=Code}"
DisplayMemberPath="Line">
<ListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding Line}" />
</GridView>
</ListView.View>
</ListView>
</DockPanel>
I have also attempted to set the DataContext in the code behind contructor, with no luck, ex.:
this.DataContext = this;
EDIT: Moving this line to after the line of code that creates the collection fixed things (along with the other changes suggested).
And I also tried to explicitly set the ItemsSource in code (in my click handler):
this.lstCode.ItemsSource = this.Code;
I've looked at a number of examples but I'm still missing something here (not really a surprise).
Uh, you're trying to do something simple with some terrible magic ;)
Your binding should look like {Binding Path=Code}
. To make this work you should also set DataContext
to this
, just like you wrote. This should give you simplest binding. Magic with finding ancestors is not necessary in here.
In advanced applications you should rather use Model - View - ViewModel pattern and set data context to ViewModel object rather than to this
, but just for testing and trying WPF out, this approach should be ok.
Here is some sample:
<Window x:Class="binding_test.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>
<ListView ItemsSource="{Binding Path=Code}" />
</Grid>
And code behind:
using System.Collections.ObjectModel;
using System.Windows;
namespace binding_test
{
public partial class MainWindow : Window
{
public ObservableCollection<int> Code { get; set; }
public MainWindow()
{
InitializeComponent();
Code = new ObservableCollection<int>();
Code.Add(1);
this.DataContext = this;
}
}
}
And here is how you should create listview
for your sample. You have special class and you probably don't want to display ToString()
result on each object. To display element any way you could imagine, you should use data template and there create controls and bind them to properties of element, that was in list you've bind ListView
.
<ListView ItemsSource="{Binding Code}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Line}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With