I'm new to this and Google isn't helping me this time. I was able to follow some examples and populate a DataGrid and modify a database, but ListView is giving me a problem. Here is my class:
public class GlobalDataviews : INotifyPropertyChanged
{
...
//Billable data table
//Populated elsewhere with "SELECT ID, Value FROM BillableTable;"
private DataTable mBillable;
public DataView Billable()
{
return mBillable.DefaultView;
}
}
Here is my XAML snippets:
<Window.Resources>
<ObjectDataProvider x:Key="GlobalDataviews" ObjectType="{x:Type local:GlobalDataviews}" />
<ObjectDataProvider x:Key="BillableData" ObjectInstance="{StaticResource GlobalDataviews}" MethodName="Billable" />
</Window.Resources>
And now for my ListView:
<ListBox Name="listBox1" DataContext="{StaticResource BillableData}" SelectedValuePath="ID" DisplayMemberPath="Value"/>
I'm probably missing something very simple. What is the correct method? I would also like to bind the selected value (no multiselect) to another property from my code. Can anyone help? Not sure why I'm getting so confused.
If you are setting DataContext, you have to set the ItemsSource property to bind data.
<ListBox x:Name="listBox1" DataContext="{StaticResource BusinessData}" ItemsSource="{Binding}" SelectedValuePath="ID" DisplayMemberPath="Value" />
Otherwise, you can bind the ItemsSource directly as follows:
<ListBox x:Name="listBox1" ItemsSource="{Binding Source={StaticResource BusinessData}}" SelectedValuePath="ID" DisplayMemberPath="Value" />
You are missing the binding for ItemsSource.
Something like this:
<ListBox Name="listBox1" DataContext="{StaticResource BusinessData}" ItemsSource="{Binding myCollection}" SelectedValuePath="ID" DisplayMemberPath="Value"/>
Where myCollection is a property that exposes your list.
Related
Is there a keyword to directly bind to the DataContext and not to an attribute of it?
I heard about the workaround with a Self Object. My problem is that I open a Window, and give an ObservableCollection as argument, which is set to the DataContext.
Here the WPF(xaml.cs) ctor
public Depot(ObservableCollection<ObservableCollection<ItemManager.Item>> totalDepot)
{
this.FullDepotList = totalDepot;
this.DataContext = FullDepotList[1];
InitializeComponent();
}
The XAML Code snippet where I would preferably bind to the DataContext directly or to "this":
<WrapPanel>
<ListBox
ItemsSource="{Binding this, UpdateSourceTrigger=PropertyChanged}"
ItemTemplate="{DynamicResource ItemWithCoolTooltipTemplate}"
Focusable="False">
</ListBox>
</WrapPanel>
To bind directly to the DataContext and not to an attribute of it, don't write any binding Path. Make it just {Binding}. UpdateSourceTrigger=PropertyChanged is not needed because ItemsSource doesn't change from view.
<ListBox
ItemsSource="{Binding}"
ItemTemplate="{DynamicResource ItemWithCoolTooltipTemplate}"
Focusable="False">
</ListBox>
alternatively use Path=. to code "bind entire DataContext here" requirement
<ListBox
ItemsSource="{Binding Path=.}"
ItemTemplate="{DynamicResource ItemWithCoolTooltipTemplate}"
Focusable="False">
</ListBox>
any tricks with RelativeSource/ElementName are usually necessary to change binding source. In this case DataContext (binding source) is simply inherited from parent Window.
You can try the following trick.
Add name property to your Window - <Window ... Name="myWindow" ...>
Use such a construction to bind to the property or whatever you need - <ListBox ItemsSource="{Binding Path=DataContext, ElementName=myWindow}" ... />
My MainView has a ViewModel called MainViewModel. MainViewModel creates a dialog and I want the dialogs ViewModel to be the already existing MainViewModel
To create the dialog from the MainViewModel I do
var MyInnerDlg = new MyInnerDlgView();
MyInnerDlg.DataContext = this;
MyInnerDlg.ShowDialog();
In the dialog I have a ListBox which I bind to a collection from my MainViewModel
public ObservableCollection<MyItemViewModel> MyList { get; set; }
XAML of the dialog
<Border Margin="5" BorderThickness="2">
<ListBox ItemsSource="{Binding MyList}" DisplayMemberPath="{Binding MyList.Name}" />
</Border>
The Name property is in MyItemViewModel. With the above code I get the error:
Name property not found in MainViewModel.
How can I refer to each of the items Name property?
DisplayMemberPath should probably not be a Binding. Change it to the property name of the property that you want to display, i.e. "Name"
<ListBox ItemsSource="{Binding MyList}" DisplayMemberPath="Name" />
Also, a general suggestion is not to have public setters on lists, since you can get unindented behavior. Instead, use a backing field and remove the setter.
Try changing :
<ListBox ItemsSource="{Binding MyList}" DisplayMemberPath="{Binding MyList.Name}">
To:
<ListBox ItemsSource="{Binding MyList}" DisplayMemberPath="{Binding Name}">
Or try adding:
<Page.Resources>
<local:MyItemViewModel x:Key="DataContext" />
</Page.Resources>
<ListBox DataContext="{StaticResource DataContext}" ItemsSource="{Binding MyList}" DisplayMemberPath="{Binding MyList.Name}"> </ListBox>
Usually i add a ViewModel in the xaml file itself.
<Page.Datacontext>
<local:MyItemViewModel/>
</Page.Datacontext>
This is my XAML:
<UserControl x:Class="SearchResultsBox">
<ListBox ItemsSource="{Binding SearchResults}" SelectedItem="{Binding Selected}"
Style="{StaticResource ListBoxStyle1}"
ItemContainerStyle="{StaticResource SearchItemContainerStyle}"
Background="{StaticResource DefaultBackground}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Background="Transparent">
<local:Forecast_SearchResults_ListView_Data/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</UserControl x:Class="SearchResultsBox">
I want to be able to reuse this listbox and just slap on a new datatemplate from the external context:
<local:SearchResultsBox>
<DataTemplate = {ForecastDataTemplate}/>
</local>
And it will put this DataTemplate into the ListBox.ItemTemplate property. Is this even possible? If so, how? If not, is there another way to achieve a similar effect?
you may use as follows
<local:SearchResultsBox ItemTemplate="{StaticResource ForecastDataTemplate}" />
and you can wire up the property to the underlying ListBox
eg
add a name to listbox
<ListBox x:Name="list" ... />
add a property wiring
public DataTemplate ItemTemplate
{
get { return list.ItemTemplate;}
set { list.ItemTemplate = value;}
}
I would like to enable live sorting of ListBox items bound to an ObservableCollection; I would also like to enable the live sorting exclusively via my XAML markup (if possible). As things stand, the list is properly sorted on application startup, but items are simply appended (not sorted) to the ListBox when new items are added to the ObservableCollection.
In my viewmodel I have the following public property:
public ObservableCollection<Equipment> EquipmentList { get; set; }
Equipment is an auto-generated class from Entity Framework which contains a public string property named 'Description'. This is my sort target.
My XAML has the following DataTemplate which is intended to enable the live sorting:
<DataTemplate x:Key="EquipmentDescriptionTemplate"
DataType="{x:Type e:Equipment}">
<DataTemplate.Resources>
<CollectionViewSource x:Key="SortedEquipmentList"
Source="{Binding Path=Description,
Mode=OneWay,
UpdateSourceTrigger=PropertyChanged}"
IsLiveSortingRequested="True">
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="Description"
Direction="Ascending"/>
</CollectionViewSource.SortDescriptions>
<CollectionViewSource.LiveSortingProperties>
<clr:String>Description</clr:String>
</CollectionViewSource.LiveSortingProperties>
</CollectionViewSource>
</DataTemplate.Resources>
<TextBlock Text="{Binding Path=Description}" />
</DataTemplate>
And finally the XAML ListBox item:
<ListBox x:Name="EquipmentList"
ItemsSource="{Binding Path=EquipmentList, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}"
ItemTemplate="{StaticResource EquipmentDescriptionTemplate}"
IsSynchronizedWithCurrentItem="True"
SelectedItem="{Binding EquipmentSelection, UpdateSourceTrigger=PropertyChanged}"
Grid.ColumnSpan="2" Grid.Row="1" Margin="5,5,5,5"/>
There's a lot of extra attributes which I added in my desperate attempts to get the live sorting to work (when in doubt, guess wildly!). I've left them in so folks can see what I've tried, and snicker.
How do I enable live ListBox sorting via XAML?
You'll want to bind the ItemsSource to the CollectionViewSource, not to the underlying collection:
<ListBox x:Name="EquipmentList"
ItemsSource="{StaticResource SortedEquipmentList}"
...
/>
Place the CollectionViewSource somewhere above, in your page's resource dictionary. Bind its source to the underlying collection ("EquipmentList"):
<CollectionViewSource x:Key="SortedEquipmentList"
Source="{Binding EquipmentList.View}"
IsLiveSortingRequested="True">
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="Description" Direction="Ascending"/>
</CollectionViewSource.SortDescriptions>
<CollectionViewSource.LiveSortingProperties>
<clr:String>Description</clr:String>
</CollectionViewSource.LiveSortingProperties>
</CollectionViewSource>
I have a list of observable collection of UserControl in my MVVM silverlight project. I want to give them as source to a listbox datasource. How can I achieve this.
<ListBox VerticalAlignment="Stretch" Style="{StaticResource Menu}" ItemsSource="{Binding Menus}" DisplayMemberPath="Libelle" SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
<ItemsControl ItemsSource="{Binding Menus.UnderControl}" /> </ListBox>
Thanks.
Let us say you have a UserControl called myUserControl1, and myUserControl1.Menus is an ObservableCollection.
and you wish to bind myListBox1.ItemsSource to myUserControl1.Menus. Then you should use the ElementName key word in your binding. For example:
<my:CustomControl x:Name="myUserControl1" />
<ListBox x:Name="myListBox1"
ItemsSource="{Binding Menus,ElementName=myUserControl1}" />