Binding ComboBox Item with a text property of different DataContext - wpf

I have a ComboBox as below. What I want is to bind the SelectedItem value to a Text property of a DataContext so that another DataTemplate can show the Image. Please note that the ComboBox and target Image elements are on two different DataTemplates so that's why I need to update the Text property (ImageName) of DataContext in the backend.
<ComboBox x:Name="cboOverlay" Grid.Row="0" Grid.Column="1" SelectedIndex="0" >
<ComboBoxItem Name="BC_OL" IsSelected="True">
<StackPanel Orientation="Horizontal">
<Image Source="Images\BC_OL.jpg" Width="100" Height="25" Canvas.Top="0" Canvas.Left="0" />
<TextBlock Width="100" VerticalAlignment="Center" TextAlignment="Center"><Bold>Image1</Bold></TextBlock>
</StackPanel>
</ComboBoxItem>
<ComboBoxItem Name="Indian_OL">
<StackPanel Orientation="Horizontal">
<Image Source="Images\Indian_OL.jpg" Width="100" Height="25" Canvas.Top="0" Canvas.Left="0" />
<TextBlock Width="100" VerticalAlignment="Center" TextAlignment="Center"><Bold>Image2</Bold></TextBlock>
</StackPanel>
</ComboBoxItem>
</ComboBox>
<Image Source="{Binding Path=Image}" Width="81" Height="25" Canvas.Top="0" Canvas.Left="0" />

You can set each item to have a specific data context.
I'm not sure in your xaml which item you are trying to set, I think it's the last line the
<Image Source="{Binding Path=Image' ... />
You can just specify the data context for that control.
Edit In reponse to comments
Since you are trying to get the selected item from the combo box and trying to send that over to the image, why not just pass it in as a value into the class that is holding the image.
I think you could do this in xaml but I'm not entirely sure how to do it.

It seems like you're trying to do something like this:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<DockPanel>
<TextBox DockPanel.Dock="Top" x:Name="Source">x1</TextBox>
<ComboBox DockPanel.Dock="Top" x:Name="myComboBox"
SelectedValue="{Binding ElementName=Source, Path=Text, Mode=TwoWay}">
<sys:String>1</sys:String>
<sys:String>22</sys:String>
<sys:String>333</sys:String>
<sys:String>4444</sys:String>
</ComboBox>
<TextBlock DockPanel.Dock="Top"
Text="{Binding ElementName=myComboBox, Mode=OneWay, Path=SelectedItem.Length}"/>
</DockPanel>
</Page>
The ComboBox is bound to the text of the TextBox using two-way binding, so when you select an item from the ComboBox it updates the TextBox, and when you type a value into the TextBox that's in the ComboBox's list it changes the selected item in the ComboBox.
The TextBlock is bound to a property of the selected item in the ComboBox. Whenever the selected item changes, whether because the user selected a new one or the value in the TextBox changed, the TextBlock gets updated.
But I'm confused by all your talk about data contexts. None of the objects in the example you posted have data contexts.

Related

WPF Mouse Binding on Listbox Item Template Inconsistent

I have a listbox which binds to an observable collection of a custom type which displays each item through my data template:
<ListBox x:Name="ListBox" Style="{StaticResource CustomListBox}" ItemsSource="{Binding HandStats}" Height="410" Width="150" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding HoleCards[0].CardParts.Value}" Margin="2"/>
<Image Source="{Binding HoleCards[0].SuitImagePath}" Width="10" Height="10" Margin="2"/>
<TextBlock Text="{Binding HoleCards[1].CardParts.Value}" Margin="2"/>
<Image Source="{Binding HoleCards[1].SuitImagePath}" Width="10" Height="10" Margin="2"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Runs:" Margin="2"/>
<TextBlock Text="{Binding NumberOfRuns}" Margin="2"/>
<TextBlock Text="Players:" Margin="2"/>
<TextBlock Text="{Binding NumberOfPlayers}" Margin="2"/>
</StackPanel>
<StackPanel.InputBindings>
<MouseBinding Gesture="LeftClick" Command="{Binding Path=DataContext.PopulateReport, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
CommandParameter="{Binding ElementName=ListBox, Path=SelectedItem}"/>
</StackPanel.InputBindings>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Image of my listbox:
http://imgur.com/a/QGz8z
Now ideally when I click anywhere in the stack panel for each item, the item will be selected and the command will be fired. But my problem is that the item selection and the command firing is not working as it should.
The item will only become selected if I click in between the text blocks or in the empty space to the right of the text blocks, but the command will not be fired. The command will only fire once I have firstly selected the item, and then click again onto one of the text blocks or one of the images.
I'm still quite new to WPF so if I'm not making much sense please let me know, thanks in advance :)
So instead of using input bindings I decided to use a different method. I created a property in my vm and bound this to the selected item of my list. So now every time I select a new item (which works perfectly now) the property is updated in my vm. Simple!
Try to set the Background property of the StackPanel to Transparent:
<StackPanel Orientation="Vertical" Background="Transparent">
...
If it doesn't have a Background the click events won't be raised as expected.

Set Text on combobox while getting data

I'm trying to display a default text in a ComboBox while I'm fetching data from a source, but it doesn't show anything.
<ComboBox
Grid.Row="1"
Grid.Column="2"
Text="Hepper"
ItemsSource="{Binding Builds}"
SelectedItem="{Binding SelectedBuild}"
DisplayMemberPath="VersionNo"
IsReadOnly="True"
IsEnabled="{Binding SelectedBuildEnable}"
VerticalAlignment="Top"
HorizontalAlignment="Left"
Width="180"
Height="30"
MinWidth="180" />
you can try to set the ComboBox.SelectedValue Property instead of ComboBox.Text.
I prefer to show another TextBlock above the ComboBox to display a default text:
<!-- don't forget to define the converter in your resources -->
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</UserControl.Resources>
<!-- your Control -->
<ComboBox
Grid.Row="1"
Grid.Column="2"
x:Name="ComboBoxElement"
ItemsSource="{Binding Builds}"
SelectedItem="{Binding SelectedBuild}"
DisplayMemberPath="VersionNo"
IsReadOnly="True"
IsEnabled="{Binding SelectedBuildEnable}"
VerticalAlignment="Top"
HorizontalAlignment="Left"
Width="180"
Height="30"
MinWidth="180" />
<TextBlock
Grid.Row="1"
Grid.Column="2"
Visibility="{Binding IsEnabled, ElementName=ComboBoxElement, Converter={StaticResource BooleanToVisibilityConverter}}"
IsHitTestVisible="False"
Text="Hepper"
VerticalAlignment="Top"
HorizontalAlignment="Left"
Margin="15,5" />
I guessed that your ComboBox becomes enabled if the data is fetched. Otherwise you have to use another binding for the visibility.
According to MSDN, the ComboBox.Text property
Gets or sets the text of the currently selected item.
Therefore, you could temporarily add an item into your ComboBox with your required message, select it and then remove it before filling the ComboBox when your data arrives.

How to make Buttons in ListBox all the same width

My WPF application contains a window that has a single ListBox in it. The View Model for the window contains an ObservableCollection of DomainViewModel objects.
The window defines the following DataTemplate:
<DataTemplate x:Key="DomainTemplate" DataType="DomainViewModel">
<Border BorderBrush="{Binding Converter={StaticResource BrushConverter}, Path=IsSelected}"
BorderThickness="2"
Name="SelectedBorder">
<Button Click="SelectDomain_Click"
Content="{Binding Path=Name}"
FontSize="16"
FontWeight="Bold"
Height="60"
HorizontalAlignment="Stretch" />
</Border>
</DataTemplate>
And here's the ListBox's declaration:
<ListBox FontSize="16"
FontWeight="Bold"
Grid.Row="2"
ItemsSource="{Binding Path=Domains}"
ItemTemplate="{StaticResource DomainTemplate}"
Name="DomainListBox" />
When the window renders, each button is exactly wide enough to display the text in its Content property. But that's not what I want. I want each button to be the width of the ListBox, which is going to vary with the width of the window itself.
How do I get the Buttons to keep their width set to the ListBox's width?
<ListBox HorizontalContentAlignment="Stretch"
.../>

datatemplate listbox selected item

here's my xaml:
<Window x:Class="WpfTest.Search"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Search" Height="600" Width="1024">
<Window.Resources>
<DataTemplate x:Key="listBoxTemplate" xmlns:ns="clr-namespace:MyConverters">
<StackPanel Orientation="Horizontal">
<StackPanel.Resources>
<ns:ImageConverter x:Key="MyImageConverter" />
</StackPanel.Resources>
<Image Source="{Binding Path=thumb, StringFormat=/WpfTest;component/Images/{0}, Converter={StaticResource MyImageConverter}}" Height="100" Width="130" Margin="5"></Image>
<StackPanel Orientation="Vertical" Width="247">
<TextBlock Text="{Binding recipeName}" Height="60" Padding="15" FontSize="16" HorizontalAlignment="Stretch" VerticalAlignment="Center"></TextBlock>
<TextBlock Text="{Binding cuisine}" Height="60" Padding="15" FontSize="16" HorizontalAlignment="Stretch" VerticalAlignment="Center"></TextBlock>
</StackPanel>
</StackPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<ListBox Margin="12,96,0,0" Name="lstSearchResult" HorizontalAlignment="Left"
VerticalAlignment="Top" Width="704" Height="445" ItemsSource="{Binding Tables[0]}" ItemTemplate="{StaticResource listBoxTemplate}" SelectionChanged="lstSearchResult_SelectionChanged">
</ListBox>
<TextBox Height="31" HorizontalAlignment="Left" Margin="12,49,0,0" Name="txtSearchRecipe" VerticalAlignment="Top" Width="518" FontSize="16" />
<Button Content="Search" Height="31" HorizontalAlignment="Left" Margin="555,49,0,0" Name="btnSearchRecipe" VerticalAlignment="Top" Width="161" Click="btnSearchRecipe_Click" />
</Grid>
</Window>
now i want to open a new form based on the item I clicked on the listbox, passing the new form the data from the selected item's textblock. how do i do that?
If I'm reading this correctly you don't need to do anything special to access the TextBlock controls in the DataTemplate. You just need to take advantage of your bindings by adding a SelectedItem binding using TwoWay binding to your ListBox.
If you're using MVVM, I would suggest you map a Command on your button click event to your View Model passing the SelectedItem as the command parameter. Then, in the command handler, cast the SelectedItem to the type you expect (this should be the type of object in the collection you've bound to your ListBox ItemsSource). You can then send the properties bound to the TextBlocks to the view model of your new window. If setup propertly these items should exist in your SelectedItem. Then set the window's DataContext to the corresponding window viewmodel and show it.
If you're just using code behind, simply cast the SelectedItem to the type used in the ListBox ItemsSource collection. Then pass the properties bound to the TextBlocks to the new window. Then show the window.

How to make a WPF ComboBox to handle click on an overlying TextBlock?

I have a TextBlock which is over a ComboBox and I want the combobox popup (dropdown) apear when I click on it.
<Grid>
<ComboBox Name="tstcmb" Height="27" HorizontalAlignment="Left" Margin="29,92,0,0" VerticalAlignment="Top" Width="131" SelectedIndex="1" >
<ComboBoxItem>a</ComboBoxItem>
<ComboBoxItem>aaaa</ComboBoxItem>
</ComboBox>
<TextBlock Text="skdkdkdk" Background="Green" Height="16" HorizontalAlignment="Left" Margin="29,92,0,0" VerticalAlignment="Top" Width="131" />
</Grid>
Is it possible?
Set IsHitTestVisible="False"
<TextBlock IsHitTestVisible="False".../>
In that way the TextBlock doesn't intercept mouse clicks and allows them to be handled by the ComboBox underneath.

Resources