I have a class named MyWindow the derives from Window. I use the MVVM pattern so in code-behind I have the following field:
public MyViewModel ViewModel = new MyViewModel();
ViewModel contains a collection of Person, and all I'd like to do is to bind a ComboBox to this collection, show Person.Name as the header for each Person.
I would also like to have another field in ViewModel that will be data-bound to the selected item.
Please help me.
Well firstly you have to set the datacontext of your window to the viewmdodel in the constructor if you have not already done so:
this.DataContext = MyModelView;
Then you can set the ComboBox as follows:
<ComboBox ItemsSource={Binding Persons} SelectedItem={Binding CurrentPerson,Mode=TwoWay} DisplayMemberPath="Name"/>
Where Persons is the Collection of Persons and Current Person is the Property the selected person will be bound to.
Assign the modelView to the MyWindow.DataContext property. This makes it available for data binding.
Define the data binding in the combobox xaml like this:
<ComboBox ItemsSource="{Binding PersonCollection}"
DisplayMemberPath="Name"
SelectedValue="{Binding SelectedPerson}" >
</ComboBox>
This assumes that your modelView has a property PersonCollection which is a collection of Person objects, a property Name on the Person object, and a property SelectedPerson on the modelView of type Person.
Related
Is it possible in XAML to set a binding to a property that contains the property to bind to.
Usual binding:
<ListBox ... ItemsSource="{Binding ListItems}"
xaml gets the list from ListItems
what I'd like
<ListBox ... ItemsSource="{Binding *ListName}"
where the ListName object holds the property name to bind to, e.g. ListItems.
Depending on user actions ListName could be changed.
What I'm hoping to do is to avoid having a bunch of combo-boxes.
I thought it might be similar to RelativeSource
https://learn.microsoft.com/en-us/dotnet/api/system.windows.data.binding.path?view=windowsdesktop-6.0
I want to bind TabItems from list to TabControl:
<TabControl Name="TabsControl" ItemsSource="{Binding}"/>
TabObject is generated in code behind:
private List<TabObject> tabsList = new List<TabObject>();
TabObject MyTab = new TabObject(Tabitem tabitem, object genericObject);
tabsList.Add(MyTab);
TabsControl.DataContext = tabList
How to bind only TabItems object from tabsList to TabsControl, is it possible without creating a separate list for TabItems?
You can use DisplayMemberPath and SelectedValuePath to use tabItem as name and as selectedValue.
Your TabControl would end up like this:
<TabControl Name="TabsControl" ItemsSource="{Binding}" DisplayMemberPath="Tabitem" SelectedValuePath="Tabitem"/>
I wrote Tabitem because i don't know that the name of the property of type Tabitem of the object of type TabObject is called. if you access the item as tabObject.Item obviously you would have to write there only Item.
I hope I was helpful.
Xaml:
<ComboBox Grid.Row="1"
Name="CmbClasse"
Grid.Column="3"
Margin="5,5,5,5"
ItemsSource="{Binding DataContext.Classeses}"
SelectedValuePath="ClasseId"
DisplayMemberPath="ClasseName"
SelectedValue="{Binding DataContext.CurrentSelectedPersonagem.IdClasse, Mode=TwoWay}"/>
When I open my application, the ComboBox do not have display any default item. But the item list is working, have all the items on it. Please help, if a image is needed just ask.
Thanks.
Here is a method I use all the time.
Firstly, your View Model should have two properties, one to represent the collection, and the other to represent the selected item.
public IEnumerable<YourObject> MyObjects { get; private set; }
public YourObject SelectedObject { get; private set; }
Note: It would be a good idea to use an ObservableCollection for MyObjects, and also implement INotifyPropertyChanged. Use this only if you need to create brand new instances of your collection in the View Model.
Your ComboBox should then bind to these properties, like so:
<ComboBox ItemsSource="{Binding MyObjects}"
SelectedItem="{Binding SelectedObject}"
...
/>
Now, here comes the magic. When you create your collection, simply set the SelectedObject to be the FirstOrDefault item in the list.
private void LoadData()
{
//TODO: Load the data into the collection
//Set the first item
this.SelectedObject = MyObjects.FirstOrDefault();
}
This will ensure that the first item is always selected. You do not need to implement INotifyPropertyChanged on the SelectedObject property unless you are planning on manually changing the value of this property in your View Model.
Scenario:
A list of user control of MyControl type:
public List<MyControl> Controls { get; set; }
public MyControl SelectedControl { get; set; }
A ComboBox with the ItemsSource linked to the Controls property:
<ComboBox ItemsSource="{Binding Path=Controls}" SelectedItem="{Binding Path=SelectedControl}" DisplayMemberPath="HeaderTitle" >
The problem is that the ComboBox shows the items correctly but when I select an Item it doesn't appear in the ComboBox. Why?
PS: HeaderTitle is a DependencyProperty of the MyControl type.
I think this is a duplicate of WPF - Combobox SelectedItem not getting set?
Therefore I'd like to quote Heinz K's answer https://stackoverflow.com/a/3506262/6071619
I had the same problem and solved it by overriding the Equals() Method in my CustomObject and compared the Id Property.
If the item that is selected is not the same instance that is contained in the List, you must override Equals() in the CustomObject to let the ComboBox know that it is the same object.
If it's the same instance, maybe it's only a simple thing such as setting the BindingMode to TwoWay:
SelectedItem="{Binding Path=CustomSettingProperty,Mode=TwoWay}"
try to bind it like this..
<ComboBox ItemsSource="{Binding Controls}" SelectedItem="{Binding SelectedControl, Mode=TwoWay}" DisplayMemberPath="{Binding HeaderTitle}" >
you dont really need to have the selected property bound to its class... it can be just a string also. so just store the selected item in type string and then work on getting the items from your list that match that selected item.
Try setting the DataContext for the ComboBox?
<ComboBox DataContext="{Binding Controls}" ItemsSource="{Binding Controls}" DisplayMemberPath="HeaderTitle">
You shouldn't have to bind the SelectedItem property as long as the ItemsSource and DisplayMemberPath are set.
I have created a user control in wpf which consists of a textbox and a listview. Now, I want to bind a class object to the list view from the form where I will use this control. So, basically I want to dynamically set the binding for the listview.
This might be simple but I am new to wpf which is making this a giant task for me. Please suggest a solution for this.
You need to bind your ListView's ItemsSource property to a collection of your class instances (I recommend using ObservableCollection for this). You can place the collection into ListView's DataContext, for example. Then the binding will be just
<ListView ItemsSource={Binding} .../>
It is more useful to create a class to contain this collection along with any other objects that your UserControl may require and pass the instance of this class to UserControl's DataContext. This refers to MVVM pattern.
EDIT
You can set DataContext either in code-behind or in xaml. Let's say we have a class with the collection:
public class ViewModel
{
public ViewModel()
{
Products = new ObservableCollection<Product>()
{
new Product("book"),
new Product("chair"),
new Product("table"),
new Product("bookshelf"),
}
}
ObservableCollection<Product> Products { get; set; }
}
Here's how to set UserControl's DataContext in code:
userControl.DataContext = new ViewModel();
where userControl is an instance of your UserControl.
Here's how to do in in xaml:
<UserControl ...
xmlns:vm="namespace_containing_class_ViewModel">
<UserControl.DataContext>
<!-- Following line instantiates the ViewModel class and calls its parameterless constructor -->
<vm:ViewModel />
</UserControl.DataContext>
...
<ListView ItemsSource="{Binding Products}"/>
...
</UserControl>
Both variants do exactly the same thing. Note that ItemsSource="{Binding Products}" means that the Binding.Path property is set to "Products" and this path will be searched for in ListView's DataContext. If ListView's DataContext is not explicitly set (as in the mentioned above case) it's DataContext is the same as its Parent's DataContext. If the parent's DataContext is not set - then it's the same as parent's parent's DataContext and so on. So in this case ListView's DataContext is the same as UserControl's DataContext and is a ViewModel class instance, that containes collection of Products. Ta-da! :)