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.
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
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! :)
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.
For some reason I have to initialize the ListBox items in behind code, the reason is too complication to tell.
The LoadFamily() is called during WPF UserControl show up.
public void LoadFamily()
{
DataTemplate listItemTemplate = this.FindResource("ManDataTemplate") as DataTemplate;
foreach (Person man in family)
{
ListBoxItem item = new ListBoxItem();
item.DataContext = man;
item.ContentTemplate = listItemTemplate;
// other initialize for item object
this.ActivityList.Items.Add(item);
}
}
In my xmal file, I define a DataTemplate.
<DataTemplate x:Key="ManDataTemplate" DataType="{x:Type local:Person}">
<TextBlock Text="{Binding Path=Name}"/>
</DataTemplate>
But the ListBox only contains empty text block, the person's Name doesn't not display. I don't know why, maybe the data binding is wrong, but how to do it in behind code.
Thanks for your any help! (WPF 3.5 or 4.0)
/////////////////////////////////////////////////////////////
Thanks for all your help. I found where I was wrong.
I should not add ListBoxItem into ActivityList.Items, one is UIElement, the other is >DataCollection. They are two different thing.
I should modify the code as follow:
foreach (Person man in family)
{
this.ActivityList.Items.Add(man);
ListBoxItem item = this.ActivityList.ItemContainerGenerator.ContainerFromItem(man) as ListBoxItem;
item.ContentTemplate = listItemTemplate;
// other initialize for item object
}
I don't see the benefit of creating the listboxitems manually. Just set the ItemsSource of the Listbox to the list of person (family).
There could be binding error. That's the reason why the textblock is empty. Check the Output window of VisualStudio, it will display the binding errors if exist.
HTH