I'm having problem with binding Collection do ListView.
public static ObservableCollection<ParagonViewClass> mparagonViewList = new ObservableCollection<ParagonViewClass>();
public ObservableCollection<ParagonViewClass> paragonViewList
{
get
{
return mparagonViewList;
}
}
In method, when user add new item, I'm adding it to list:
paragonViewList.Insert(0, newPar);
Also tried with mparagonViewList.Insert(0, newPar);
Itemssource in xaml file:
<ListView Grid.Row="1" Name="paragonListView1" ItemsSource="{Binding paragonViewList}" .../>
#EDIT: Listview have DataTemplate (Grid with labels - im prettu sure that binding is ok, becouse it works with just simply setting myListVIew.ItemsSource = myLis;)
It looks like when I click on product to add to listview it does insert to database, but I cannot see that product on listview. Probably there's little stupid problem, but I cant really find it ;)
Thanks for any answers!
Looking at the code you supplied, it is hard to figure out what you are doing wrong, if anything. So, I have thrown together a little sample application that works (from the WPF point of view anyway).
My model is called ItemModel, rather than ParagonViewClass, and is defined as follows
public class ItemModel
{
public ItemModel() { }
public string Text { get; set; }
}
My Xaml is
<Window x:Class="StackOverflow._20799346.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:common="clr-namespace:StackOverflow.Common;assembly=StackOverflow.Common"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="MainWindow" Height="350" Width="525">
<DockPanel>
<StackPanel Orientation="Horizontal" DockPanel.Dock="Top">
<Button Content="Add Item" Click="AddItem_OnClick" />
</StackPanel>
<ListView ItemsSource="{Binding Path=Items}">
<ListView.ItemTemplate>
<DataTemplate DataType="{x:Type common:ItemModel}">
<TextBlock Text="{Binding Path=Text}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</DockPanel>
</Window>
Note the DataContext being bound to RelativeSource Self, allowing the code behind to be used as the ViewModel. I usually prefer to create a separate ViewModel class but this approach has its advantages as one can event directly from a control into the ViewModel, rather than mucking around with commands.
The code behind, now the view model, looks like
public partial class MainWindow : Window
{
private ObservableCollection<ItemModel> items;
public MainWindow()
{
InitializeComponent();
}
public ObservableCollection<ItemModel> Items { get { return items ?? (items = new ObservableCollection<ItemModel>()); } }
private void AddItem_OnClick(object sender, RoutedEventArgs e)
{
Items.Add(new ItemModel() { Text = Items.Count.ToString(CultureInfo.CurrentCulture) });
}
}
I have utilised a lazy load technique on the Items property. It will only be instantiated when it is accessed. For simplicity, when the Add Item button is clicked, I am adding a new item with its text set to the count of the Items collection.
You should be able to past this code into a new WPF application project, fix the namespacing in the xaml file and run it.
Now, as hinted at above by Rohit Vats, the Items property does not require a Setter. The ObservableCollection itself notifies the WPF binding subsystem when an item has been added or removed via both the INotifyPropertyChanged and INotifyCollectionChanged interfaces, both of which it implements.
I know this does not directly answer your question but with out further information (ie code) about the original problem, it is not possible to know what is going wrong.
Hopefully the example helps.
NOTE: I have removed exception management for brevity.
Related
[Edit]: I figured out how to do this on my own. I posted my solution in the hope that it will save someone else a few days of Googling. If you are a WPF guru, please look at my solution and let me know if there is a better / more elegant / more efficient way to do this. In particular, I am interested in knowing what I don't know... how is this solution going to screw me down the road? The problem really boils down to exposing inner control properties.
Problem:
I am creating some code to auto-generate a data-bound GUI in WPF for an XML file. I have an xsd file that can help me determine the node types, etc. Simple Key/Value elements are easy.
When I parse this element:
<Key>value</Key>
I can create a new 'KeyValueControl' and set the DataContext to this element. The KeyValueControl is defined as a UserControl and just has some simple bindings on it. It works great for any simple XElement.
The XAML inside this control looks like this:
<Label Content={Binding Path=Name} />
<TextBox Text={Binding Path=Value} />
The result is a line that has a label with the element name and a text box with the value that I can edit.
Now, there are times where I need to display lookup values instead of the actual value. I would like to create a 'KeyValueComboBox' similar to the above KeyValueControl but be able to specify (based on information in the file) the ItemsSource, DisplayMemberPath, and ValueMemberPath. The 'DisplayMemberPath' and 'ValueMemberPath' bindings would be the same as the KeyValueControl.
I don't know if a standard user control can handle this, or if I need to inherit from Selector.
The XAML in the control would look something like this:
<Label Content={Binding Path=Name} />
<ComboBox SelectedValue={Binding Path=Value}
ItemsSource={Binding [BOUND TO THE ItemsSource PROPERTY OF THIS CUSTOM CONTROL]
DisplayMemberPath={Binding [BOUND TO THE DisplayMemberPath OF THIS CUSTOM CONTROL]
SelectedValuePath={Binding [BOUND TO THE SelectedValuePath OF THIS CUSTOM CONTROL]/>
In my code, I would then do something like this (assuming that this node is a 'Thing' and needs to display a list of Things so the user can select the ID:
var myBoundComboBox = new KeyValueComboBox();
myBoundComboBox.ItemsSource = getThingsList();
myBoundComboBox.DisplayMemberPath = "ThingName";
myBoundComboBox.ValueMemberPath = "ThingID"
myBoundComboBox.DataContext = thisXElement;
...
myStackPanel.Children.Add(myBoundComboBox)
So my questions are:
1) Should I inherit my KeyValueComboBox from Control or Selector?
2) If I should inherit from Control, how do I expose the inner Combo Box's ItemsSource, DisplayMemberPath, and ValueMemberPath for binding?
3) If I need to inherit from Selector, can someone provide a small example of how I might get started with that? Again, I'm new to WPF so a nice, simple example would really help if that's the road I need to take.
I ended up figuring how how to do this on my own. I'm posting the answer here so that others can see a solution that works, and maybe a WPF guru will come by and show me a better/more elegant way to do this.
So, the answer ended up being #2. Exposing the inner properties turns out to be the right answer. Setting it up is actually pretty easy.. once you know how to do it. There aren't many complete examples of this (that I could find), so hopefully this one will help someone else that runs into this problem.
ComboBoxWithLabel.xaml.cs
The important thing in this file is the use of DependencyProperties. Note that all we're doing right now is just exposing the properties (LabelContent and ItemsSource). The XAML will take care of wiring the internal control's properties to these external properties.
namespace BoundComboBoxExample
{
/// <summary>
/// Interaction logic for ComboBoxWithLabel.xaml
/// </summary>
public partial class ComboBoxWithLabel : UserControl
{
// Declare ItemsSource and Register as an Owner of ComboBox.ItemsSource
// the ComboBoxWithLabel.xaml will bind the ComboBox.ItemsSource to this
// property
public IEnumerable ItemsSource
{
get { return (IEnumerable)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
public static readonly DependencyProperty ItemsSourceProperty =
ComboBox.ItemsSourceProperty.AddOwner(typeof(ComboBoxWithLabel));
// Declare a new LabelContent property that can be bound as well
// The ComboBoxWithLable.xaml will bind the Label's content to this
public string LabelContent
{
get { return (string)GetValue(LabelContentProperty); }
set { SetValue(LabelContentProperty, value); }
}
public static readonly DependencyProperty LabelContentProperty =
DependencyProperty.Register("LabelContent", typeof(string), typeof(ComboBoxWithLabel));
public ComboBoxWithLabel()
{
InitializeComponent();
}
}
}
ComboBoxWithLabel.xaml
The XAML is pretty straightforward, with the exception of the bindings on the Label and the ComboBox ItemsSource. I found that the easiest way to get these bindings right is to declare the properties in the .cs file (as above) and then use the VS2010 designer to setup the binding source from the properties pane. Essentially, this is the only way I know of to bind an inner control's properties to the base control. If there's a better way to do it, please let me know.
<UserControl x:Class="BoundComboBoxExample.ComboBoxWithLabel"
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"
mc:Ignorable="d"
d:DesignHeight="28" d:DesignWidth="453" xmlns:my="clr-namespace:BoundComboBoxExample">
<Grid>
<DockPanel LastChildFill="True">
<!-- This will bind the Content property on the label to the 'LabelContent'
property on this control-->
<Label Content="{Binding Path=LabelContent,
RelativeSource={RelativeSource FindAncestor,
AncestorType=my:ComboBoxWithLabel,
AncestorLevel=1}}"
Width="100"
HorizontalAlignment="Left"/>
<!-- This will bind the ItemsSource of the ComboBox to this
control's ItemsSource property -->
<ComboBox ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType=my:ComboBoxWithLabel,
AncestorLevel=1},
Path=ItemsSource}"></ComboBox>
<!-- you can do the same thing with SelectedValuePath,
DisplayMemberPath, etc, but this illustrates the technique -->
</DockPanel>
</Grid>
</UserControl>
MainWindow.xaml
The XAML to use this is not interesting at all.. which is exactly what I wanted. You can set the ItemsSource and the LabelContent via all the standard WPF techniques.
<Window x:Class="BoundComboBoxExample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="86" Width="464" xmlns:my="clr-namespace:BoundComboBoxExample"
Loaded="Window_Loaded">
<Window.Resources>
<ObjectDataProvider x:Key="LookupValues" />
</Window.Resources>
<Grid>
<my:ComboBoxWithLabel LabelContent="Foo"
ItemsSource="{Binding Source={StaticResource LookupValues}}"
HorizontalAlignment="Left"
Margin="12,12,0,0"
x:Name="comboBoxWithLabel1"
VerticalAlignment="Top"
Height="23"
Width="418" />
</Grid>
</Window>
For Completeness Sake, here is the MainWindow.xaml.cs
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
((ObjectDataProvider)FindResource("LookupValues")).ObjectInstance =
(from i in Enumerable.Range(0, 5)
select string.Format("Bar {0}", i)).ToArray();
}
}
I tried your solution but it fails for me. It does not pass the value over to inner control at all. What I did is declaration of same dependency properties in outer control and bound inner to outer like that:
// Declare IsReadOnly property and Register as an Owner of TimePicker (base InputBase).IsReadOnly the TimePickerEx.xaml will bind the TimePicker.IsReadOnly to this property
// does not work: public static readonly DependencyProperty IsReadOnlyProperty = InputBase.IsReadOnlyProperty.AddOwner(typeof(TimePickerEx));
public static readonly DependencyProperty IsReadOnlyProperty = DependencyProperty.Register("IsReadOnly", typeof (bool), typeof (TimePickerEx), new PropertyMetadata(default(bool)));
public bool IsReadOnly
{
get { return (bool) GetValue(IsReadOnlyProperty); }
set { SetValue(IsReadOnlyProperty, value); }
}
Than in xaml:
<UserControl x:Class="CBRControls.TimePickerEx" x:Name="TimePickerExControl"
...
>
<xctk:TimePicker x:Name="Picker"
IsReadOnly="{Binding ElementName=TimePickerExControl, Path=IsReadOnly}"
...
/>
</UserControl>
I'm working on a small "fun" project using WPF/MVVM/Prism which main component is a TreeView showing the file structure of a certain path. The idea how the ViewModel works is taken from Josh Smiths' article http://www.codeproject.com/Articles/28306/Working-with-Checkboxes-in-the-WPF-TreeView.
I actually need two things:
I'd like to get a list of checked items of the TreeView-View, presented in a another view (let's say List-View) and also show that the their state has changed.
I'd like to modify the List-View, which shall then be reflected within the TreeView.
Somehow I did not find a nice solution, as the hierarchical ViewModel used by Josh makes it hard for me to get hold on a "shared" model useable within both ViewModels.
But let's have a look at my code before stating my question:
My "ExplorerView" uses a hierarchical datatemplate and looks as follows:
<UserControl x:Class="MyFunProject.Views.ExplorerView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ViewModel="clr-namespace:MyFunProject.ViewModels"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True">
<UserControl.Resources>
<HierarchicalDataTemplate DataType="{x:Type ViewModel:ItemBaseViewModel}" ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal">
<CheckBox Focusable="True" IsChecked="{Binding IsChecked}" VerticalAlignment="Center" ToolTip="{Binding Path}">
<TextBlock Text="{Binding Name}" />
</CheckBox>
</StackPanel>
</HierarchicalDataTemplate>
</UserControl.Resources>
<TreeView ItemsSource="{Binding Children}" />
</UserControl>
Following Josh's article, the ExplorerViewModel exhibits a child as a List<CheckableItemViewModel> with only one entry - which in fact has other childs directories or files. Directories itself again have childs.
public class ExplorerViewModel : BindableBase
{
private List<CheckableItemViewModel> childred;
public List<CheckableItemViewModel> Children
{
get { return childred; }
set { SetProperty(ref childred, value); }
}
public ExplorerViewModel(IExplorerModel ExplorerModel)
{
CheckableItemViewModel root = new CheckableItemViewModel();
AddChildrenToNode(root, ExplorerModel.GetCheckableItems());
root.Initialize(); // initialize children (and each children its own children, etc...)
Children = new List<CheckableItemViewModel> { root });
}
private void AddChildrenToNode(CheckableItemViewModel root, IList<CheckableItem> items)
{
foreach(var item in items)
{
var child = new CheckableItemViewModel(item);
var dirItem = item as DirectoryItem; // it's a directory and so it has childs
if(dirItem != null)
{
AddChildrenToNode(child, dirItem.Items);
}
root.Children.Add(child);
}
}
}
And now to my questions:
How do I connect my CheckableItemViewModel to a "kind of" global CheckableItemModel? If I inject the constructor by resolving a registered instance (unity container) I've got the problem, that I cannot do that if I'd like to have two ExplorerViews simultanously (or don't I?).
How do I inject if every CheckableItemViewModel also needs constructor parameters (is this the case where to use parameter override?)
How do I get a retrieve a list of the actual selected items (or when and where should I update the according model)?
How do I get a "changed" flag if one of the CheckableItemViewModel is altered?
Let me know if i missed a piece of my puzzle.
Thanks for any suggestions.
I'm trying to get my head around MVVM, i'm currently stuck on how to handle navigation.
Currently I have a page and within that page is a frame, that frame is responsible for framing in various other pages. Navigation was previously handled with a drop down box and on selection changed it would navigate that way.
I'm not sure how I could do this without touching the frame from the model view which would end up breaking mvvm.
In the end what I am trying to accomplish is, clicking on the combobox, selecting an item and then having then frame below navigate to the correct view.
I'm not using Prism or any other framework with MVVM, just trying to do it all manually.
The ComboBox would display an ObservableCollection of frame items exposed by your main viewmodel, and the viewmodel will have another property for the selected item.
Your main viewmodel and the frame item viewmodels all inherit from a ViewModelBase class which implements INotifyPropertyChanged, and maybe some other stuff.
So, C#:
public ObservableCollection<ViewModelBase> FrameItems { get; protected set; }
private ViewModelBase _selectedFrameItem;
public ViewModelBase SelectedFrameItem {
get { return _selectedFrameItem; }
set {
value = _selectedFrameItem;
// Defined in ViewModelBase
OnPropertyChanged();
}
}
Your main viewmodel will populate FrameItems in its constructor:
public MainViewModel()
{
FrameItems = new ObservableCollection<ViewModelbase> {
new IceCreamMenu(),
new SmurfOptions(),
new MagicSparklePonyFourierTransformConfiguration()
};
}
Every frame item is a subclass of ViewModelBase. It exposes properties with notifications, including ObservableCollections of any set of child things it may have. And we'll display it by writing a datatemplate for it in just a bit.
Let's assume that you've given your ViewModelBase class a String Title { get; set; } property. Or maybe you'll want to write a subclass of ViewModelBase that introduces Title; your call. For now let's put it in ViewModelBase for simplicity.
XAML -- this leaves out all the layout, but you don't need that here.
<ComboBox
ItemsSource="{Binding FrameItems}"
SelectedItem="{Binding SelectedFrameItem}"
DisplayMemberPath="Title"
/>
<Frame Content={Binding SelectedFrameItem}" />
OK, but how on earth does it know what to do with SelectedFrameItem?!
Easy! Write a resource dictionary called, say, ViewModelDataTemplates.xaml, and merge it into App.xaml so its contents are "visible" in any XAML in your application.
App.xaml
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- Source is a relative path from project root directory -->
<ResourceDictionary Source="ViewModelDataTemplates.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
...plus whatever theme stuff or whatever.
In ViewModelDataTemplates.xaml, define data templates for your frame item classes.
Say you've got an IceCreamMenu viewmodel, with a collection of Flavors
public ObservableCollection<IceCreamFlavor> Flavors { get; protected set; }
...and a SelectedFlavor. You'd define the namespace vm appropriately with an xmlns:vm attribute on the resource dictionary.
ViewModelDataTemplates.xaml
<DataTemplate DataType="{x:Type vm:IceCreamMenu}">
<Grid>
<ListBox
ItemsSource="{Binding Flavors}"
SelectedItem="{Binding SelectedFlavor}"
/>
</Grid>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:IceCreamFlavor}">
<StackPanel Orientation="Horizontal">
<Border
Height="20"
Width="20"
Margin="4"
Background={Binding Color, Converter={StaticResource ColorToBrushConverter}}"
/>
<Label Content="Name" />
</StackPanel>
</DataTemplate>
If you've got existing UserControls that you want to use via datatemplates, that's easy: Say you've got a NotesTabView UserControl that's a view for your NotesTabViewModel, you could define a DataTemplate like this:
<DataTemplate DataType="{x:Type vm:NotesTabViewModel}">
<vw:NotesTabView />
</DataTemplate>
#EdPlunkett: As an alternative to DataTemplate for each view, you can bind your frame to selected page viewmodel using ViewModelToViewConverter like I did here: https://stackoverflow.com/a/31721236/475727
Implicit DataTemplates and DataTemplateSelectors are unique to WPF and XAML, so people think it's recommended solution, but I think it's not suitable for navigation. It feels hackish and it smells with violation of DRY principle.
I cannot figure out how to set ItemsSource to my Pivot programatically. I am using MVVM Light ViewModelLocator where my ViewModel is registered. Then I set the DataSource of my Page and in the xaml of the Pivot I set its ItemsSource. But in the ViewModel I have other collection that I want to change at runtime to be an ItemsSource for my Pivot:
Here is my ViewModelLocator:
public class ViewModelLocator
{
public ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
SimpleIoc.Default.Register<TripTypeViewModel>();
}
public TripTypeViewModel TripTypeVM
{
get
{
return ServiceLocator.Current.GetInstance<TripTypeViewModel>();
}
}
public static void Cleanup() {}
}
XAML of the page:
<Page
...
DataContext = "{Binding Source={StaticResource Locator}, Path=TripTypeVM }">
...
<Pivot x:Name="TripsSegmentsPivot" Title="Locator" Foreground="#FF888888" Style="{StaticResource PivotStyle1}" SelectionChanged="Pivot_SelectionChanged" Margin="0" Grid.Row="1" ItemTemplate="{StaticResource TripTypeTemplate1}" ItemsSource="{Binding TripTypeViewModelDataSource}">
<Pivot.HeaderTemplate>
<DataTemplate>
<Grid>
<TextBlock Text="{Binding id}"/>
</Grid>
</DataTemplate>
</Pivot.HeaderTemplate>
</Pivot>
So in the ViewModel except TripTypeViewModelDataSource i have also TripTypeViewModelDataSource2.
In the xaml.cs of the View I would usually do this:
TripsSegmentsPivot.ItemsSource = ViewModelLocator.TripTypeVM.TripTypeViewModelDataSource;
TripsSegmentsPivot.ItemsSource = ViewModelLocator.TripTypeVM.TripTypeViewModelDataSource2;
but its not working..
There are many ways to bind but let's discuss a few...
Directly to the Pivot object itself: http://msdn.microsoft.com/en-us/library/system.windows.controls.itemscontrol.itemssource(v=vs.105).aspx
MyPivot.Itemsource=mycollection;
You could use a collection view source: http://msdn.microsoft.com/en-us/library/system.windows.data.collectionviewsource(v=vs.110).aspx Visual Stuidio will create these if you drag a container control onto the surface, it also put code in the code behind so you can "wire-it-up" It works very nicely with any collection type and fully integrates with LINQ.
You can set up observable collection in the View Model and Bind to them from the view. The easiest way to do this is to create a Static Instance of the View Model in the View XAML itself because visual studio property page will "See" the view model and allow you to pick the property as an item source. All you need to do is implement INPC or create a Dependency Property (where needed) and you are all set to go. You need this to notify the view when a property changes. https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=using%20inotifypropertychanged
If you need to change collections at run time, the CollectionViewSource is dead-simple to use.. like this...
MyCollectionViewSource.Source = MyCollection.Where(p=>p.Name==SelectedName).ToList();
MyCollectionViewSource.Source = MyCollection.Where(p=>p.ID > 500).ToList();
MyCollectionViewSource.Source = MyOtherCollection.ToList();
MyCollectionViewSource.Source = JustSayNoToObamaCare();
In the current code it shows:
ItemsSource="{Binding TripTypeViewModelDataSource}"
If you use a CollectionViewSource like this:
ItemsSource="{Binding MyCVS}"
You can then change the collection at will in the viewmodel like this.
MyCVS.Source = Collection1;
MyCVS.Source = Collection2;
Update: I've updated the code based on your help so far, and still no luck. When the application loads the ListBox has no items. I assign junk values to Customers in the windows's contructor, and then am also trying to set the ListBox's DataContext as follows:
CustomerList.DataContext = Customers;
--- Original Question (with updated code) ---
I'm having trouble with databinding in a WPF project.
I have a class, Customer, as follows:
public class Customer
{
public String Name { get; set; }
public String Email { get; set; }
}
In my XAML's code behind I have a collection of customers as follows:
public List<Customer> Customers { get; set; }
I'm trying to bind each customer to a ListBox with a ListItemTemplate displaying the customer's information (name/email) in TextBoxes along with a button which locks/unloacks the TextBoxes (sets the IsEnabled property to true or false).
What's the best way to go about this?
So far I've been tryingt he following with no success.
In the XAML I currently have the following (ignoring the toggle part for now, I'm just trying to get the collection itself to be listed.):
<Window.Resources>
<CollectionViewSource x:Key="Customers" Source="{Binding Path=Customers, Mode=TwoWay}"/>
<DataTemplate x:Key="Customer">
<StackPanel Orientation="Horizontal">
<TextBox Content="{Binding Name}" />
<TextBox Content="{Binding Email}" />
</StackPanel>
</DataTemplate>
</Window.Resources>
<StackPanel>
<ListBox ItemsSource="{Binding Source={StaticResource Customers}}"
ItemTemplate="{StaticResource ResourceKey=Customer}"
Name="CustomerList"
Height="300" />
</StackPanel>
You need to change
ItemsSource="{Binding Source=Customers}"
to
ItemsSource="{Binding Source={StaticResource Customers}}" DataContext="{StaticResource Customers}"
Code similar to the updated one works for me after changing
<TextBox Content="{Binding Name}" />
to
<TextBox Text="{Binding Name}" />
As TextBox doesn't have Content property(like a Label), the former refused to compile in VS.
Well, it is set to Text in definition:
[ContentPropertyAttribute("Text")]
public class TextBox : TextBoxBase, IAddChild
But I thought it is only used between the brackets(<TextBox>Like so</TextBox>)?
Could this be the source of the problem?
Try setting the ItemsSource of your CustomerList as follows: ItemsSource="{Binding}". You've set the DataContext of the ListBox to the list of customers, you need to set the ItemsSource to the same collection, hence, the direct binding.
Another thing that you can do, in case you prefer to use the CollectionViewSource, is to set the DataContext of your window to the same class DataContext=this, because without this, the resource definition won't be able to locate the "Customers" collection that you defined in the code behind. If you do this, however, you don't need CustomerList.DataContext = Customers; because you're directly assigning the ItemsSource to a static resource, not relatively to the DataContext.
One more thing. I think you should give the CollectionViewSource and the corresponding collection in the code behind different names. This isn't going to cause a runtime issue, but it makes it hard to maintain the code ;)
Hope this helps :)