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
Related
I have an issue with binding in ComboBox. I have searched in Google and so, but I haven't been able to find the answer.
I have silverlight form with combobox like this:
<ComboBox x:Name="FirmBox"
Grid.Row="23"
Grid.Column="1"
Grid.ColumnSpan="2"
Margin="5,5,5,0"
SelectedValuePath="{Binding Path=Value, Mode=TwoWay}"
SelectedItem="{Binding Path=Firm, Mode=TwoWay}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Value}"/>
<TextBlock Text="{Binding Path=Key}"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
And the ItemsSource is an
ObservableCollection<KeyValue<String, KeyValue<String, String>>>
So I've figured out how to display this in right way, but I don't know how to bind the selected item to my KeyValuePair<String, String>
field. That does not seem obvious to me. So I need to bind the value of selected item to my field and don't know how to do it.
Thank you.
The solution was simple as always:
SelectedValuePath="Value"
SelectedValue="{Binding Path=Firm, Mode=TwoWay}">
I am trying to bind a dependency property to a collection's current selection and for reasons I can't seem to grasp, the binding does not update when the collection changes.
In the example below, I show two example. One is updating correctly (on the textblock/run), and the other only displays the initial element and doesn't change when the data grid selection changes.
<Grid>
<Grid.Resources>
<CollectionViewSource Source="{Binding Path=List}" x:Key="myViewModel"/>
<my:UpdateNotWorking MyObjModel="{Binding Source={StaticResource myViewModel}, Path=CurrentItem}" x:Key="updateNotWorking" />
</Grid.Resources>
<DataGrid ItemsSource="{Binding Source={StaticResource myViewModel}}" Name="mylistbox"/>
<TextBlock TextWrapping="Wrap" FontWeight="Bold" Foreground="#FF50CEFF" FontSize="24" TextAlignment="Center" Height="75">
<Run Text="{Binding Source={StaticResource myViewModel}, Path=text}" Foreground="#FF00E200" />
</TextBlock>
<TextBox Text="{Binding Source={StaticResource updateNotWorking}, Path=MyObjModel.text}" Height="22"/>
</Grid>
My dependency property in this example is "MyObjModel" on the "UpdateNotWorking" dependency object which is instantiated from the xaml code.
I would appreciate any information as to why my property is not updating correctly.
Example Project
Paste this XAML into your MainWindow.
<Grid>
<Grid.Resources>
<CollectionViewSource Source="{Binding Path=List}" x:Key="myViewModel" />
<my:UpdateNotWorking x:Key="updateNotWorking" />
</Grid.Resources>
<DataGrid ItemsSource="{Binding Source={StaticResource myViewModel}}" Name="mylistbox"
SelectedItem="{Binding Source={StaticResource updateNotWorking}, Path=MyObjModel, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock TextWrapping="Wrap" FontWeight="Bold" Foreground="#FF50CEFF" FontSize="24" TextAlignment="Center"
Height="75">
<Run Text="{Binding Source={StaticResource myViewModel}, Path=text}" Foreground="#FF00E200" />
</TextBlock>
<TextBox Text="{Binding Source={StaticResource updateNotWorking}, Path=MyObjModel.text, UpdateSourceTrigger=PropertyChanged}"
Height="22" />
</Grid>
What it is now doing is setting updateNotWorking's MyObjModel property based on the DataGrid's SelectedValue, with UpdatePropertyTrigger set to PropertyChanged to see the changes immediately. No longer do we need to define updateNotWorking's property through the List's CurrentItem because it is not going to change just by selecting it with a DataGrid. You can keep it set, but it is not required as we are doing all the manual labor with the DataGrid SelectedValue.
When I put this code into my XAML file:
<TextBlock Text="{Binding Name}" FontSize="16" Margin="15,0,0,0" />
It shows me Name value but when I try show it via ListView:
<ListView x:Name="ItemListView"
ItemsSource="{Binding Items}"
Margin="60,0,0,10">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Name}"
FontSize="24" Margin="5,0,0,0" TextWrapping="Wrap" />
<TextBlock Text="{Binding Artist}"
FontSize="16" Margin="15,0,0,0"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
It doesn't show up :( What could be wrong?
If the page inherits from LayoutAwarePage, like it will by default when created from a template, the DataContext will be set to a property named DefaultViewModel. Properties exposed in your codebehind will not be bound to.
You are looking at two different objects in the sample. In the textbox you are looking at the Name of the object in the datacontext, in the listview you are looking at the Items[x].Name for each item you bind to. If you need to reference the Name from the datacontext rather than the Items collection you will need to bind the source to an Element not inherit it.
how to get value from the textblock , which is present in listbox ....
here is the code xaml :
<ListBox Height="707" HorizontalAlignment="Left" Margin="12,0,0,0" Name="listBox1" VerticalAlignment="Top" Width="456" Background="White" Foreground="#FF09090C" ItemsSource="{Binding}" SelectionChanged="listBox1_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Name="textBlock3" FontSize="18" Foreground="Blue" Margin="2" Text="{Binding Title.Text}" TextWrapping="Wrap" />
<TextBlock FontSize="16" Foreground="Gray" Margin="2" Text="{Binding Summary.Text}" TextWrapping="Wrap" />
<TextBlock FontSize="1" Foreground="Gray" Margin="2" Text="{Binding Id}" TextWrapping="Wrap" Visibility="Collapsed" />
<Button Name="h1" Content="Press" Height="10" Width="40"></Button>
<TextBlock Foreground="Gray" Margin="2" Text="________________________________________________________________________________________" FontSize="8"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
You don't get the value directly from the TextBlock.
Instead what you do is bind the SelectedItem to a property on your viewmodel. To get the value of the TextBlock directly would violate the priciples of MVVM (if you are using that pattern). The viewmodel presents the data, it has no clue how that data is being rendered to the UI. IOW it has no idea there are three TextBlocks.
<ListBox Height="707" SelectedItem={Binding MyViewModelProperty} >
... etc ...
This means that every time the selected item is changed, the new value will be populated into the bound property on the viewmodel. All you have to do then is access that object - it's as easy as that. This means you may also possibly be able to get rid of your SelectionChanged event hookup, depending on what it is doing.
However if you insist on getting the instance of the template used to present any particular data item in a list control, then this is the way to do it programmatically:
myListBox.ItemContainerGenerator.ContainerFromItem(myDataItem);
This will return you the StackPanel and its contents, you can then either use FindName() or just enumerate the child controls to find the one you are interested in.
FrameworkElement element = myListBox.ItemContainerGenerator.ContainerFromItem(myDataItem) as FrameworkElement;
if (element != null)
FrameworkElement child = element.FindName("myChildName");
I have a combobox in wpf which is binded to some property (another object). Because I need to show two properties of that object i used DataTemplate inside combobox. Now when combobox is in focus I can't select some value by typing few starting letters (without DataTemplate it is possible).
<ComboBox Height="23" HorizontalAlignment="Left" Margin="104,14,0,0" Name="tipDokumentaCombo" VerticalAlignment="Top" Width="241" TabIndex="0" ItemsSource="{Binding Path=TipoviDokumenta}" SelectedValue="{Binding Path=Potvrda.Tip}" SelectedValuePath="Tip" SelectionChanged="tipDokumentaCombo_SelectionChanged">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Tip}" />
<TextBlock Text=" (" />
<TextBlock Text="{Binding Path=OpisDokumenta}" />
<TextBlock Text=")" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Set TextSearch.TextPath to the property that should be searched.
Update
Because the abvove solution seems not to work for you, try to set the search text manually for the container:
<ComboBox.ItemContainerStyle>
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="TextSearch.Text" Value="{Binding Tip}" />
</Style>
</ComboBox.ItemContainerStyle>
Add DisplayMemberPath to the property on which lookup should work on.
Setting DisplayMemberPath worked for me even when itemtemplate is present.
Based on the comment discussion, the solution that works is to add both IsTextSearchEnabled="True" and TextSearch.TextPath="Tip" in the ComboBox tag.
For example (re-writting the question code sample - removing some not useful to the example code to reduce complexity)
<ComboBox Name="tipDokumentaCombo" TabIndex="0" ItemsSource="{Binding Path=TipoviDokumenta}" SelectedValue="{Binding Path=Potvrda.Tip}" SelectedValuePath="Tip" SelectionChanged="tipDokumentaCombo_SelectionChanged" IsTextSearchEnabled="True" TextSearch.TextPath="Tip">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Tip}" />
<TextBlock Text=" (" />
<TextBlock Text="{Binding Path=OpisDokumenta}" />
<TextBlock Text=")" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Disclaimer: I am not the original author. This answer is fabricated from the existing comments. Attribution should be given to #mersadk who post, most of this answer's details in the comments. I test it and verified that this works in my (similar) environment - issue.