Binding to multiple objects - c#

In my current situation, I have a list to display in my app. This list should be based on two things. Description, and a color, which is based on the current state of each element. The challenge is that description and color are set in each their own tables. Is there a way to set my itemsource/ bindingcontext to two different objects/ tables? Or is there a different way to solve this problem?
This is my XAML file binding to the table where the description is accessible:
<StackLayout>
<ListView x:Name="postListView" ItemSelected="Handle_ItemSelected" >
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Description}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
In my code behind postListview is set to one of the tables:
PostListView.itemSource = _chekc;
I am not able to set two different itemsources, thus not able to bind to color in my other table _answer.
Any workaround for this?

This is a common problem: you have to display a list that is a combination of data from more than one table. The fact that you cannot set the ItemsSource to more than one source is not a bug in the ListView that has to be worked around...it is a limitation in your design...you need to construct a view model that properly handles this situation.
So one way of doing this is to have a PostRowView class that is a pairing of color and description from your two tables and a ObservableCollection that manages the PostRowViews. You bind the ItemsSource of the ListView to the observable collection.

Related

How to bind dynamically generated TextBoxes to DataGrid values in WPF?

My problem is basically described in the title of this topic.
I have a datagrid which is dynamically filled with various entries:
<DataGrid
x:Name="searchResult"
AutoGenerateColumns="True"
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding Path=SearchResult}" />
Next to it is a bunch of TextBoxes, also dynamically generated:
<ItemsControl
x:Name="searchForm"
ItemTemplate="{StaticResource formInputTest}"
ItemsSource="{Binding SearchForm, UpdateSourceTrigger=PropertyChanged}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
The template I use in the ItemsControl looks basically like this:
<TextBox
Tag="{Binding Index}"
Text="{Binding ElementName=searchResult, Path=SelectedValue.a, UpdateSourceTrigger=PropertyChanged}" />
Now lets asume my datagrid has 2 columns (a and b) and I have 2 TextBoxes with identical names (a and b).
Now I want to select a datagridrow and like the two text boxes to be automatically filled with the values from the corresponding row.
Unfortunately, I don't know how to get this dynamically Binding.
If I bind the TextBox's Text-property statically to searchResult->SelectedValue.a it works fine, but as you can see, only static.
Thats what I've done in the third code-box above.
The ItemsControl, which contains the TextBoxes, has it's binding to "SearchForm". SearchForm has the property "Index", which is the name of the Column.
So, the TextBox knows the name of the column it has to be binded to. To clarify this, I binded the TextBox.Tag to Index, which works fine.
Basically, I want my TextBox-Binding to look like this:
<TextBox
Text="{Binding ElementName=searchResult, Path=SelectedValue.{Binding Index}, UpdateSourceTrigger=PropertyChanged}" />
But, as you might know, a binding inside a binding does not work.
Does anybody know how to bind these to dynamically generated objects together?
Thanks for any hint!
UPDATE 2019/03/07
Thanks dymanoid!
This has got me some progress but I'm still not at the finish line.
I created the view-model property and binded both the Datagrid-SelectedItem and the TextBox-Text property to it.
Since the SelectedItem is a kind of a dictionary (BindablePublicDictionary) I use a converter (IMultiValueConverter) at the TextboxBinding, to convert the dictionary entry to both the index of the textbox and the text/value.
This is working fine, I select a datagrid-row and the 3 dynamically generated inputfields are beeing filled.
Unfortunatelly, if I edit one of these filled textboxes, the other 2 are emptied and my datagrid is unchanged.
I implemented OnPropertyChanged, my bindings are TwoWay and the ConvertBackFunction is called and returns the data in compliance with the targetType Type from the function itself.
Does anybody have experience with the bindings/converter between a datagrid/dictionary and textboxes, especially regarding the convertBack function?

Overwrite ListBoxitem?

I'm new to WPF and I have this ListBox which I want to instantiate with a specific ListBoxItem, so the user knows what to do with the ListBox.
<ListBox Name="DbListBox"
Grid.Column="3"
HorizontalAlignment="Left"
Height="246"
Margin="0,99,0,0"
Grid.Row="1"
VerticalAlignment="Top"
Width="211"
SelectionMode="Single"
SelectedItem="{Binding Path=selectedDB,Mode=TwoWay}"
AllowDrop="True"
Drop="DbListBox_Drop">
<ListBoxItem Name="ListBoxItem" FontStyle="Italic">Drag .db file here or add below</ListBoxItem>
</ListBox>
Then I have some code which adds a collection of items to the ItemsSource of this ListBox, but I can't do that since the ItemsSource is not empty
DbListBox.ItemsSource = DbCollection;
My question is, how can I start up the ListBox with the item inserted first, and then when DbCollection is added to it, it simply overwrites the first ListBoxItem?
When using WPF properly, we'd normally have something like this, where a collection property would be data bound to the ListBox.ItemsSource property:
<ListBox ItemsSource="{Binding SomeCollectionProperty}" />
Once we have this XAML, we don't need to touch the ListBox again, as we can add or remove items from the data bound collection and they will magically appear (or disappear) from the ListBox:
SomeCollectionProperty.Add(new SomeDataType());
SomeCollectionProperty.Remove(someItemFromCollection);
The SomeDataType used here is up to you... it depends on what you want to display in your items. If it was just a plain string for example, then you could simply do this to add your initial item into the collection:
SomeCollectionProperty.Add("Drag .db file here or add below");
If you wanted to make that item look different to the others then you'd need to data bind a custom class that has a Text property and FontStyle property for example. You could data bind these properties in a DataTemplate to design each item to be exactly as you want it. However, that's a completely different question.
To find out more about these things, you can read the Data Binding Overview and Data Templating Overview page on MSDN.

Select ListView item when combobox/textbox is selected WPF MVVM

I have a ListView which contains a collection of objects as itemssource and the selected object as SelectedItem.
<ListView Margin="5 0 5 0" ItemsSource="{Binding ObjectCollection}" SelectedItem="{
Binding SelectedObject}" Grid.Row="1">
Inside the ListView.View I have several GridViewColumns which each have a CellTemplate
<GridViewColumn CellTemplate="{StaticResource ReferenceToCellTemplate}" Header="{
Binding ColumnName, Converter={StaticResource upperConverter}}" Width="90"
HeaderContainerStyle="{StaticResource StaticGridViewColumnHeaderStyleWhite}"/>
An example of such a template:
<DataTemplate x:Key="ReferenceToCellTemplate">
<ComboBox ItemsSource="{Binding PossibleValuesForProperty, UpdateSourceTrigger=
PropertyChanged}" SelectedItem="{Binding SelectedProperty, UpdateSourceTrigger=
PropertyChanged}" SelectionChanged="Protocol_ComboBox_SelectionChanged"/>
</DataTemplate>
Now for the issue:
Say that I have 2 comboboxes in this listview. for example a combobox with different software and another with the different versions of this software.
Whenever the software has changed in a certain row, the possible versions should be updated.
The question:
How do I know which object the software combobox belongs too so that I can adjust the possible versions for this object?
When you change the value inside the combobox, this doesn't mean that the row is selected. So when I try to adjust the versions along with the selected row, I might as well be adjust the wrong row.
So the way I see it there are 2 possibilities:
Select the given row whenever something inside that row is adjusted/selected
Get to know which row the changed/selected control is in without selecting it
Any help would be much appreciated.
The solution is to not use an event handler for when the property is changed but just to handle the change in the properties for the row object. So when the property for "software" changes, call a method which adjust the "PossibleVersions" property for this software. All of this inside the VM for the row object.
Basic beginner MVVM mistake I guess

How to create a template to display data from a class in WPF

I have a data layer which is returning lists of classes containing data. I want to display this data in my form in WPF. The data is just properties on the class such as Class.ID, Class.Name, Class.Description (for the sake of example)
How can i create a custom control or template an existing control so that it can be given one of these classes and display its data in a data-bound fashion.
Thanks :)
You could use a ListBox and set its ItemsSource property to the list containing your data items. Then you define a DataTemplate for your type like this:
<DataTemplate x:Key="MyDataTemplate" DataType="{x:Type MyType}">
<StackPanel>
<TextBlock Text="{Binding ID}"/>
<TextBlock Text="{Binding Name}"/>
<TextBlock Text="{Binding Description}"/>
</StackPanel>
</DataTemplate>
...and tell the ListBox to use this DataTemplate by setting the ItemTemplate property.
It is also sufficient to just define the DataTemplate as above and give it no key. Then it will be used for all items which have the respective type.
BTW: You can find a more detailed example in MSDN on the page for the ItemTemplate property.

How do build a VS-like propertypanel in WPF?

I got a TreeView containing different objects from different classes. Now I want to build a propertypanel, which shows up different content, depenting on what object/class is selected in the TreeView. What is the best way to build such panel? Differnt panels and collapsing panels depending on the selection(Whould make implementing the ObserverPattern this easier for me?)? Or an other approach?
I would bind the property panel (which could be just a ContentControl) to the SelectedItem in the TreeView:
<ContentPanel Content="{Binding SelectedItem, ElementName=_treeView}"/>
Then I would use DataTemplates to show the correct panel for each class of item you have:
<DataTemplate DataType="{x:Type local:SomeClass}">
<Label>This is displayed for SomeClass</Label>
</DataTemplate>
<DataTemplate DataType="{x:Type local:SomeOtherClass}">
<Label>This is displayed for SomeOtherClass</Label>
</DataTemplate>
Obviously your DataTemplates can be as complex as needed to display the various classes present in the TreeView.
Do you mean a property grid?

Categories

Resources