Show multiple columns from database in one combobox - c#

I want to show in one combobox content from two database columns. I would like to show "Name Surname" but I don't know how. I'm working in C# (.NET) using MVVM pattern. "Name" and "Surname" are fields from table "tblGuests".
Thanks in advance,
Vladimir

You could create an ItemTemplate for the ComboBox that binds to all the properties you want to show.
<ComboBox ItemsSource="{Binding}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=FirstName}" Padding="10,0,0,0"/>
<TextBlock Text="{Binding Path=LastName}" Padding="10,0,0,0"/>
</StackPanel>
<DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
You could even create a UserControl that can be re-used and use that:
<PersonView>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=FirstName}" Padding="10,0,0,0"/>
<TextBlock Text="{Binding Path=LastName}" Padding="10,0,0,0"/>
</StackPanel>
</PersonView>
<ComboBox ItemsSource="{Binding}">
<ComboBox.ItemTemplate>
<DataTemplate>
<PersonView/>
<DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>

Keep a string list property in Viewmodel,
populate that property in a data loading method, by combining name and surname strings,
bind string property to combo box,
<ComboBox Name="ComboBox1" ItemsSource="{Binding YourStringListProperty}"/>

Another option could be to use MultiBinding something like this
<TextBlock Name="textBox2" DataContext="{StaticResource NameListData}">
<TextBlock.Text>
<MultiBinding Converter="{StaticResource myNameConverter}"
ConverterParameter="FormatLastFirst">
<Binding Path="FirstName"/>
<Binding Path="LastName"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
This code was taken directly from msdn. Refer to it for more details

Related

WPF, Caliburn.micro : How to bind property outside of current binding context?

<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Key}"></TextBlock>
<ComboBox ItemsSource="{Binding Value}" SelectedItem="{Binging SomeProperty}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"></TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
I am inside a Dictionary , I want to bind SelectedItem="{Binging SomeProperty}" SomeProperty is a property of the ViweModel, not inside of the Dictionary. How to do that? How can I bind to properties outside of current binding context.
In case of Binding to the Window.DataContext's property, you may do it the following way with RelativeSource:
<ComboBox ItemsSource="{Binding Value}" SelectedItem="{Binding DataContext.SomeProperty, RelativeSource={RelativeSource AncestorType=Window}}">
Or in case you want to display SelectedItem for example in some TextBox (for example collection of string):
<TextBox Text="{Binding MyCollection/}"/>
<ComboBox ItemsSource="{Binding MyCollection}" IsSynchronizedWithCurrentItem="True">
MyCollection with "/" gets the current item of the ICollectionView used as DefaultView for MyCollection. Read more >>>

WPF Binding TextBlock value to display SelectedItem in ComboBox

I have a ComboBox and a couple of TextBlock fields.
I want to display the properties of a SelectedItem from the ComboBox on those Textblock's. Image
So that when I choose one of multiple user's the properties in the TextBlock will update to those of the SelectedItem. I have found an example, although it is using silverlight, and does not work entirely.
<ComboBox Grid.Row="0"
Grid.Column="0"
VerticalAlignment="Bottom"
VerticalContentAlignment="Center"
HorizontalContentAlignment="Left"
Margin="0"
Height="40"
Name="ComboBox"
ItemsSource="{Binding UserModels}"
SelectedItem="{Binding EnteredUserModel, Mode=TwoWay}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding FirstName}"
Style="{StaticResource ResourceKey=ComboBoxItemTextBlock}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</Grid>
<TextBlock Grid.Row="1"
Grid.Column="0"
Margin="0 10 0 10" >
<Run Text="{DynamicResource firstName}" />
<Run Text=": " />
<Run Text="{Binding ElementName=ComboBox, Path=SelectedItem, UpdateSourceTrigger=PropertyChanged}" />
</TextBlock>
This is what I've tried. I added Name to the ComboBox so that I can access it's SelectedItem in my TextBlock. I need to get the SelectedItem.firstname, etc. At this stage i can only access the entire objects.
Am I missing some useful binding?
In order to show the FirstName property of the SelectedItem, just use an appropriate property path, i.e. SelectedItem.FirstName:
<Run Text="{Binding ElementName=ComboBox, Path=SelectedItem.FirstName}" />
or, since SelectedItem is bound to an EnteredUserModel property in your view model:
<Run Text="{Binding Path=EnteredUserModel.FirstName}" />
Setting UpdateSourceTrigger=PropertyChanged is not necessary. It has no effect in a OneWay Binding.
You're getting the EnteredUserModel-Object, because that's the selected item of the ComboBox. If you want the displayed text you must bind to the FirstName-Property.
Alternatively you can bind to EnteredUserModel.FirstName in your TextBox

How to set a secondary control MaxWidth property to the same as another in a different container

I have this StackPanel in one grid on my form:
<StackPanel x:Name="panelWeelyBibleReading" Grid.Row="2" Grid.Column="0" Margin="2">
<Label>Bible Reading for Week:</Label>
<TextBox x:Name="textWeeklyBibleReading">PSALMS 60-68</TextBox>
</StackPanel>
<StackPanel Grid.Row="3" Grid.Column="0" Margin="2">
<Label>Opening Song:</Label>
<ComboBox x:Name="comboSongOpen" ItemsSource="{StaticResource SongTitles}">
<ComboBox.ItemTemplate>
<DataTemplate DataType="local:SongTitleItem">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Number, StringFormat='000 - '}" />
<TextBlock Text="{Binding Title}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
<ComboBox.MaxWidth>
<Binding Path="ActualWidth"
ElementName="textWeeklyBibleReading"/>
</ComboBox.MaxWidth>
</ComboBox>
</StackPanel>
Further down the form in a different grid I have this :
<StackPanel Grid.Row="3" Grid.Column="0" Margin="2">
<Label>Closing Song:</Label>
<ComboBox x:Name="comboSongEnd" ItemsSource="{StaticResource SongTitles}">
<ComboBox.ItemTemplate>
<DataTemplate DataType="local:SongTitleItem">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Number, StringFormat='000 - '}" />
<TextBlock Text="{Binding Title}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
<ComboBox.MaxWidth>
<Binding Path="ActualWidth"
ElementName="panelWeeklyBibleReading.textWeeklyBibleReading"/>
</ComboBox.MaxWidth>
</ComboBox>
</StackPanel>
Initially I tried using the same "textWeeklyBibleReading" for the MaxWidth in the second combo. But it doesn't work. No warnings. Just doesn't work. So I thought about applying a name to the previous StackPanel in teh hopes I could use it as some kind of access point. But it still doesn't work.
So my problem is that I need to set the MaxWidth on the second combo, which is in a different grid, but using the value that was calculated on the first grid combo. Am I making sense?
I would show the complete form markup if it helps.
You should edit to:
<ComboBox.MaxWidth>
<Binding Path="Width"
ElementName="textWeeklyBibleReading"/>
</ComboBox.MaxWidth>
<Binding Path=Width, ElementName=textWeeklyBibleReading/>
cause there is no property such as ActualWidth, instead it should be Width. And there is no need to write container name panelWeeklyBibleReading, just write ElementName that you need.
Update:
<ComboBox.ItemTemplate>
<DataTemplate DataType="local:SongTitleItem">
<StackPanel Orientation="Horizontal" MaxWidth="{Binding Path=Width,
ElementName=textWeeklyBibleReading}">
<TextBlock Text="{Binding Number, StringFormat='000 - '}" />
<TextBlock Text="{Binding Title}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
You should set MaxWidth of StackPanel of ComboBox cause outer StackPanel``(<StackPanel Grid.Row="3" Grid.Column="0" Margin="2">) which contains your ComboBox automatically sets Width to the outer StackPanel to your ComboBox. So I suggest to bind Width of your ComboBox to its ItemTemplate. Cause ItemTemplate has Data/template, then it is better to bind Width of ComboBox to StackPanel located into your DataTemplate.

Updating the source of a Listbox with a multibinding

I'm trying to get a multi-bound listbox to call the convert back method when items inside it change. Specifically I have a datatemplate that maps each entry to a checkbox and I'd like the source to be updated whenever a box is checked.
<ListBox x:Name="listBoxEdit" Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="3" Height="100" >
<ListBox.ItemsSource>
<MultiBinding Converter="{StaticResource selectedLoadsConverter}" >
<Binding Path="AvailableLoads"/>
<Binding Path="CurrentUnit"/>
</MultiBinding>
</ListBox.ItemsSource>
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Item1}" IsChecked="{Binding Item2}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I know the problem lies in the fact that I'm binding to to the ItemsSource property which is never actually being updated by the checkbox changing, but I can't figure out a good way to push the updates up to the source.

TextBlock binding format

How could I achieve this behavior in my ComboBox items: (n): Name
Where n and Name are two bindable properties. Right now I have n Name
This is my code:
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock>
<Run Text="{Binding n}" />
<Run Text="{Binding Name}" />
</TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
I think that adding two <Run Text="("/>, etc it can be done but there must be something more elegant in XAML.
Ok it was easy:
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}({0}): - {1}">
<Binding Path="n" />
<Binding Path="Name" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
Another way is using multiple TextBlocks like so:
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=...}"></TextBlock>
<TextBlock Text="{Binding Path=...}"></TextBlock>
</StackPanel>
</DataTemplate>
You can replace the StackPanel with a WrapPanel or whatever you like.

Categories