How to make my WPF UserControl work with CompositeCollection - wpf

I have a wpf user control which exposes an IEnumerable ItemsSource DependencyProperty. I bind this property to a ListBox control in my UserControl.
I would like to know how I can make my user control work when a CompositeCollection is given. Currently I'm utilising my control like this:
<my:uc>
<my:uc.ItemsSource>
<CompositeCollection>
<CollectionContainer Collection="{My Binding}"></CollectionContainer>
<CollectionContainer Collection="{My Binding}"></CollectionContainer>
</CompositeCollection>
</my:uc.ItemsSource>
</my:uc>
I would like this to display the contents of these CollectionContainers in the list box, but at the moment its not enumerating through the containers. The only items my listbox shows is two "System.Data.CollectionContainer" items.
[b]Edit:[/b]
The XAML designer informs me that "Property 'ItemsSource' does not support values of type 'CompositeCollection'." I think this is my problem.. but how do I make it "support" CompositeCollection?

I think that what you are getting is the ToString method of your object, which by default returns the name of the type.
Try overriding ToString and returning the value you want to see in your list.

The correct answer was to create a class that extends ItemsControl. You can not use any XAML when designing the control, but it does give you the special ItemsSource property which supports CollectionContainers. The view of the control should be defined in its ContentTemplate property.

Related

Binding with parent DataContext

I'm trying to bind combobox editor in a PropertyGrid to a list.
<dxprg:PropertyGridControl SelectedObject="{Binding SelectedEmployee}">
<dxprg:PropertyDefinition Path="EmployeeCountryID">
<dxprg:PropertyDefinition.EditSettings>
<dxe:ComboBoxEditSettings
ItemsSource="{Binding Path=DataContext.Countries, ElementName=rootWindow}"
ValueMember="CountryId" DisplayMember="CountryName" />
</dxprg:PropertyDefinition.EditSettings>
</dxprg:PropertyDefinition>
</dxprg:PropertyGridControl>
This example is from a third-party control but the problem may be just general.
The "rootWindow" DataContext has been set to a ViewModel which holds a property List(of Country) that I want have as ItemsSource in a Combobox.
I was trying to access that list by setting the Combobox ItemsSource to the rootWindow.DataContext.Countries property but I don't get any data.
Tried also all those RelativeSource FindAncestor bindings but no data appeared either.
Why can't I bind through a DataContext of a given element like this?
This became solved. The problem was not with the binding at all but realated to how I defined the third-party control: Instead of EditSettings I should have defined CellTemplate -> DataTemplate.

How to create ComboBox like UserControl in WPF

I'm trying to build an usercontrol wich is able to take elements from XAML like this:
<ComboBox >
<ComboBoxItem />
<ComboBoxItem />
<ComboBoxItem />
</ComboBox>
In the ComboBox, you can just add the Items between the ComboBox tags, and I would like to copy this, but I don't know where to start.
Finished it should look like this:
<cis:ReportControl Grid.Row="3">
<cis:ReportItem />
</cis:ReportControl>
In the cis:ReportControl, there are some Buttons and a ComboBox, and basically I only want to feed the ComboBox with Items.
The Report Item is just a ComboBoxItem with some extra properties.
Edit:
I've implemented it according to #Snowbears answer, but the problem now is that the control has itself as an item.
I think this is because I have some content, and by defining the ContentProperty to my ComboBox, it is redirected into the Box.
What can I do to avoid this?
Edit II:
It fully works now with this:
private ItemCollection reportItems;
public ItemCollection ReportItems
{
get
{
if (reportItems == null)
{
reportItems = this.ComboBoxReports.Items;
}
return reportItems;
}
}
with the [ContentProperty("ReportItems")] Attribute. ComboBoxReports is the ComboBox in the Control, and I had to inherit from ItemsControl to get it to work.
You should create property in your UserControl which will expose something implementing IList interface. Let's say this property will be named ReportItems. This property should not have setter and it should be initialized in UserControl itself either in constructor in by field initialization on backing field.
UserControl should be marked with ContentProperty attribute with your property name (ReportItems)
Internal combobox should have it's ItemsSource bound to UserControl's ReportItems property
if you look for How to Create Your own Control, You must look for two things:
Custom Control 1 or User Control 1 (it's depend on your need)
Dependency Properties (use them in control)
I think you might need to use Custom-Control. Also you can inherit your Custom-Control from ComboBox or other Controls.

Wpf SelectedItem wont work for a Combobox in a ListView

I´ve got a problem with a Combobox in a ListView.
I´ve got a class called "Substrate". This class contains an object of a class called "SubstrateType". I want to show the objects of the class "Substrate" in a Listview. Each property of the "Substrate" is presented in the columns of the Listview. For the different "SubstrateType" I want to use a combobox.
In the XAML I tried it like this:
<ComboBox Name="CBType"
ItemsSource="{Binding ElementName=SettingsSubstrate, Path=TypeList}"
SelectedItem="{Binding Path=Substrate.SubstrateType}"
DisplayMemberPath="Description"/>
In the code-behind I got two ObservableCollections. One for all Substrates and one for all possible SubstrateTypes. The combobox displays all SubstrateTypes if you click on it. But the combobox has no selecteditem if you dont select one.
http://i44.tinypic.com/2eakxav.png
Thanks in advance.
I do not know your exact code, but if your ListView rows display objects of type Substrate, then your Binding Path for the SelectedItem should be just SubstrateType because the DataContext of a ListViewItem is already set to the Substrate object:
SelectedItem="{Binding Path=SubstrateType}"
Furthermore, you need to make sure that your SubstrateType instances are actually considered as equal. If the SubstrateType instance in your Substrate object is not exactly the same as the one from the TypeList property, it will not be selected. You can fix that by overriding the Equals(...) method and define your custom comparison for equality.
If this does not work, please provide more code, e.g. the surrounding XAML and the code of Substrate and the code-behind/ViewModel/whatever.

Passing Generic lists to a WPF usercontrol

I want to create a usercontrol that takes lists of different objects. These objects would be assigned to the control at design time. Now I want to be able to use linq to object to sort this list inside the usercontrol. Can anyone give me any ideas as how to go about it?
Add a DependencyProperty of type ObservableCollection<T> to your user control class (call it MyItemsSource for example). In your containing XAML, bind that property to your Linq collection, and inside your user control, bind your ListBox (or other ItemsControl) to the property as follows:
{Binding
RelativeSource={RelativeSource
Mode=FindAncester,
AncestorType=UserControl},
Path=MyItemsSource}
Alternatively, you can set the Name property inside the user control on the top level element (the UserControl element) to for example MyUserControl, and bind against an ElementName instead of a RelativeSource as such:
{Binding ElementName=MyUserControl, Path=MyItemsSource}

How do I databind a control in an item template to the item itself, and not one of its properties?

I've got a WPF ListBox that's databound to an ObservableCollection of type Employee. In the ItemTemplate, I'm binding the content of controls to various properties, as normal. But for one of the controls in the template, I've made a custom converter class that it uses, and I'd like the converter to get passed in the Employee object itself as the value, as opposed to one of its' properties. Is this easy to do? I don't want to resort to something like adding a read only property to Employee whose getter just says return this.
Thanks in advance!
Just use
{Binding}
or
{Binding Converter={...}}
i.e. without a Path.

Resources