Link textbox to combobox - not working - wpf

I have a WPF usercontrol with a combobox & textbox. I want the textbox to hold the value of the selected item in the combobox and it works fine if I use SelectedValue in the binding path. However if I try to use the Title column of the combobox (SelectedValue.Title) the value of the textbox is overwritten but nothing is displayed. Can anyone tell me what I am doing wrong? My code sample is below. I am a newbie at this so please be kind :)
<ComboBox x:Name="ComboProject" Grid.Column="4" Grid.Row="0" TabIndex="14"
ItemsSource="{Binding Source={StaticResource Projects}, XPath=./Project}"
SelectedValuePath="#Item"
Tag="Project Number"
TextSearch.TextPath="#Item">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text= "{Binding XPath= #Item}" Width="90" />
<TextBlock Text= "{Binding XPath= #Title}" Width="220" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<TextBox x:Name="loaded" Text="{Binding Path=SelectedValue.Title, NotifyOnSourceUpdated=True, ElementName=ComboProject}" Grid.Row="2" Grid.Column="4" Tag="Project Title" TabIndex="15"/>

You set SelectedValuePath="#Item", so that's what SelectedValue has right now. Try setting it to Title and binding directly to SelectedValue:
<ComboBox x:Name="ComboProject"
ItemsSource="{Binding Source={StaticResource Projects}, XPath=./Project}"
SelectedValuePath="#Title">
<ComboBox.ItemTemplate>
...
</ComboBox.ItemTemplate>
</ComboBox>
<TextBox Text="{Binding SelectedValue, ElementName=ComboProject}" />
I removed some other code for clarity of example.
EDIT :
Ok, if you want to use SelectedValue for other purposes we can bind TextBox to SelectedItem instead. If the Title is an attribute of a selected XML node, then we can access it like this:
<TextBox Text="{Binding SelectedItem.Attributes[Title].Value, Mode=OneWay, ElementName=ComboProject}" />

Related

Define ComboBox' DataTemplate for TextBox (and define search pattern) when IsEditable is True?

I have a ComboBox whose ItemsSource is binding to a collection and the SelectedItem is binding to the properties of my VieModel. Let's call the binding properties AvailableOptions and TargetOption in ViewModel. And type of collection item and TargetOption is called MyOption. I have such requirements but I don't know how to fulfill them all:
It should be OK for the binding TargetOption to have NULL as value
I want to set a DataTemplate for the target type in TargetOption collection to be displayed in the ComboBox
If possible, I want use different DataTemplate for MyOption when then are in the drop-down of ComboBox and when one item is selected. Because my UserControl has limited space so it should be compact when item is selected and during the selection it should provide more information
As I said, I don't know how to do all of them. At first I have the XAML like this:
<ComboBox SelectedItem="{Binding SelectedOption} ItemsSource="{Binding AvailableOptions}" >
<ComboBox.ItemTemplateSelector>
<MyNameSpace:ComboBoxItemTemplateSelector ItemTemplate="{StaticResource OptionDetailTemplate}" SelectedItemTemplate="{StaticResource OptionSimpleTemplate}" />
</ComboBox.ItemTemplateSelector>
</ComboBox>
With a customized ItemTemplateSelector. I am able to do the requirement 2) and 3). My OptionDetailTemplate looks like this:
<DataTemplate x:Key="OptionDetailTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding ShortName}" />
<TextBlock Text=" | " />
<TextBlock Text="{Binding Code}" />
</StackPanel>
</DataTemplate>
and OptionSimpleTemplate looks like this:
<DataTemplate x:Key="OptionSimpleTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding ShortName}" />
<TextBlock Text=" | " />
<TextBlock Text="{Binding Code}" />
<TextBlock Text=" | " />
<TextBlock Text="{Binding Number}" />
</StackPanel>
</DataTemplate>
But now the problem is requirement 1). When the user select one option from the drop down list of the ComboBox, he can't put it as NULL back which should be allowed. This is because AvailableOption doesn't have a NULL object
I see that if I set IsEditable to True for the ComboBox, and set TextSearch.TextPath to Code, it allows the text quick search/assign and also allows to have a NULL value when the search text is totally deleted. But now when I ever select one, it only displays Code (the OptionTemplate does not have any effect any more because now it displays the selected item in a TextBox). This is not good since only Code is not enough for the user to tell what Option it is. But since I have multiple properties in MyOption class, how can I define the DataTemplate for the TextBox and also define the search routine?
I have to be honest that I didn't fully understand your first requirement and its ramifications. however, I am really just answering to let you know that you don't even need to use a DataTemplateSelector to select between your two DataTemplates. If you do not set the x:Key value on them, then they will be applied to the relevant items implicitly:
<DataTemplate DataType="{x:Type YourXamlNamespacePrefix:TargetOption}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding ShortName}" />
<TextBlock Text=" | " />
<TextBlock Text="{Binding Code}" />
</StackPanel>
</DataTemplate>
...
<DataTemplate DataType="{x:Type YourXamlNamespacePrefix:MyOption}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding ShortName}" />
<TextBlock Text=" | " />
<TextBlock Text="{Binding Code}" />
<TextBlock Text=" | " />
<TextBlock Text="{Binding Number}" />
</StackPanel>
</DataTemplate>
Furthermore, you could do all this data binding with just a single TextBlock if you use a MultiDataTrigger:
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0}|{1}">
<Binding Path="ShortName" />
<Binding Path="Code" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
Perhaps if you try clarifying your remaining problem (in your question), I might understand?

stop Text block (not Text box) from tabbing sequence

How to exclude TextBlock from tabbing sequence in SILVERLIGHT Grid XAML. I know for TextBox, we use IsTabStop false OR TabIndex -1, but same property is not avaiable for TextBlock
I have 4 controls, 1 and 4 are TextBox (editable) and 2 and 3 are TextBlock (non editable). When I tab, all the 4 are included in the tabbing sequence.
I want to exclude 2,3 (Textblocks) from tabbing. Means, If I tab from TextBox 1, focus should move directly to TextBox 4. please help.
Loaded="UserControl_Loaded">
<DataTemplate x:Key="CellEditClientAllocations" >
<TextBox Text="{Binding ClientAllocations, Mode=TwoWay}"
Style="{StaticResource GridCellTextBoxStyle}"
x:Name="tbxClientAllocations"
Loaded="TextBox_Loaded"
TextChanged="tbxClientAllocations_TextChanged"
KeyDown="tbxClientAllocations_KeyDown"
LostFocus="tbxClientAllocations_LostFocus"
GotFocus="tbxClientAllocations_GotFocus"/>
</DataTemplate>
<DataTemplate x:Key="CellAccountId">
<TextBlock Text="{Binding AccountId, Converter={StaticResource anc}}" Style="{StaticResource GridCellTextBlockStyle}" /> </DataTemplate>
<DataTemplate x:Key="CellEditAccountId">
<TextBox Text="{Binding AccountId, Converter={StaticResource anc}, Mode=TwoWay}" x:Name="tbxAccountId" LostFocus="TbxAccountIdLostFocus" TextChanged="TbxAccountIdTextChanged" GotFocus="tbxAccountId_GotFocus"/>
</DataTemplate><DataTemplate x:Key="CellAccountName"> <StackPanel>
<TextBlock VerticalAlignment="Center" Text="{Binding AccountName, Mode=TwoWay}" Foreground="{Binding IsAccountValid, Converter={StaticResource cc}}" kStyle="{StaticResource GridCellTextBlockStyle}" Name="Account" MouseRightButtonUp="" > </TextBlock> </StackPanel> </DataTemplate>
<DataTemplate x:Key="CellLotInstructions"> <StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding LotInstructions}" Style="{StaticResource GridCellTextBlockStyle}"/>
<HyperlinkButton Content="Edit" Style="{StaticResource HyperlinkButtonStyleUnderline}" IsEnabled="{Binding LotInstructionsEnabled}" Name="Lotinstructons" HorizontalContentAlignment="Center" MouseLeftButtonDown="LotinstructonsMouseLeftButtonDown" VerticalContentAlignment="Center" Click="ViewSpecifyLots_Click" Visibility="{Binding LotInstructionsEdit}" /> </StackPanel> </DataTemplate>
Try setting attached property KeyboardNavigation.TabNavigation to None.
<TextBlock KeyboardNavigation.TabNavigation="None"/>
Set Focusable="False" for the textblock
I think you may need to work on the DataGrid Column rather than the Cell content (your TextBlock) it is the Cell that is Focussed not the TextBlock.
You could assign an event handler to the CellEnter Event (accessible from the definition of the original column) and then set the DataGrids selected cell selected property to false. Not the neatest solution but it should work.
Alternatively you could create a behaviour to do this....
Hope this helps!

Binding a value to ConverterParameter

I have a combobox control in xaml. Whatever is selected in combobox, I want it to be appended to the text in below TextBox. How can this be achieved?
<TextBox Text="{Binding Entity.Value.Minvalue,
Converter={StaticResource ConverterName},
ConverterParameter=???,
Mode=TwoWay}"/>
Can we pass Entity/Property in ConverterParameter? Any pointers in the direction how it can be achieved are greatly appreciated.
Try this
<Grid x:Name="LayoutRoot" >
<ComboBox x:Name="Cmb" Background="Red" Height="35" Width="300" >
<ComboBoxItem Content="ComboBoxItem1"></ComboBoxItem>
<ComboBoxItem Content="ComboBoxItem1"></ComboBoxItem>
<ComboBoxItem Content="ComboBoxItem1"></ComboBoxItem>
<ComboBoxItem Content="ComboBoxItem1"></ComboBoxItem>
</ComboBox>
<TextBox Text="{Binding ElementName=Cmb,Path=SelectedValue.Content,Mode=TwoWay}" HorizontalAlignment="Right" VerticalAlignment="Bottom"></TextBox>
</Grid>
Mode you can decide as per your requirement..
If you want to append text every time the SelectedItem changes for the ComboBox, you can listen to the SelectionChanged event and update the text.
<StackPanel>
<ComboBox x:Name="Combo" ItemSource="{Binding MyItems}" SelectionChanged="OnComboBoxSelectionChanged">
<!-- define your template -->
</ComboBox>
<TextBlock x:Name="AppendingText" Text=""/>
</StackPanel>
In your code begind, in the OnComboBoxSelectionChanged, add to the text
// You probably want to cast SelectedItem to your model and get a property from it
AppendingText.Text += Combo.SelectedItem.ToString();

Multiselect ComboBox, Force it to always display the same text

I have a multiselect combobox that works fine. Except for the text. I want it to always have the same text ("Commodity Filter") regardless of what the user has selected.
If I set iseditable to true and the text to CommodityFilter it looks fine until the user makes a selection, then it is garbage (displays object type name). How can I hard code some text there? (Actually ideally i would databind it so it can change depending on whether anything is selected, but that would be a bonus at this point)
<ComboBox IsEditable="True" Text ="Commodity Filter" ItemsSource="{Binding Path=ActiveCommodities}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding IsSelected}"
Width="20" />
<TextBlock Text="{Binding Commodity}"
Width="100" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
I ended up creating a custom object for populating the ComboBox (which had the IsSelected property and implemented INotifyPropertyChanged) because I was creating several comboboxes to control filtering. Once I did this is was trivial to override the tostring on the customobject and pass in the appropriate text. So the xaml did not change much.
I would have preferred to overlay with a text box but that seemed to be beyond my abilities to get a polished look in a reasonable time.
<ComboBox ItemsSource="{Binding Path=ActiveFuturesMonths}"
IsEditable="True"
IsReadOnly="True"
Text="Futures Month Filter" >
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding IsSelected}"
Width="20" />
<TextBlock Text="{Binding Text}"
Width="100" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Actually the crux is in setting -
IsEditable="True"
IsReadOnly="True"
Text="Futures Month Filter"
rather than creating custom object. thanks a lot it helped.

WPF DataGrid - Problem Customizing a ComboBox

I have a Datagrid with a combo box bound column that works great as follows:
<tk:DataGridComboBoxColumn SelectedValueBinding="{Binding DefaultLocationID}"
SelectedValuePath="LocationID"
DisplayMemberPath="LocationName"
Header="Default Location"
ItemsSource="{Binding Source={StaticResource CustomerLocations}}">
</tk:DataGridComboBoxColumn>
Ultimately I want to customize the dropdown to show 'ID' and 'Name' together so a TemplateColumn seems to be the way to go. Starting small, I can't get the following simple example to work which should replace the standard DataGridComboBoxColumn. The dropdown appears fine, but when I 'select' a dropdown item, it does not accept and goes back to the previous value. I've tried variations on 'Mode=TwoWay' but no luck. Do I need a 'CellEditingTemplate' ?
DefaultLocationID is the foreign-key field being edited, while 'LocationID' is a column in 'CustomerLocations'.
<tk:DataGridTemplateColumn Header="Default Location">
<tk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox VerticalAlignment="Top"
SelectedItem="{Binding LocationID, Mode=TwoWay}"
SelectedValue="{Binding DefaultLocationID, Mode=TwoWay}"
ItemsSource="{Binding Source={StaticResource CustomerLocations}}"
SelectedValuePath="LocationID"
DisplayMemberPath="LocationName" >
</ComboBox>
</DataTemplate>
</tk:DataGridTemplateColumn.CellTemplate>
Thanks!!
Can you post the relevant parts of your CustomerLocations resource? Can you also post the type of class that your grid is binding to?
Try removing the SelectedValuePath, DisplayMemberPath and SelectedValue from the ComboBox.
If you want to display multiple pieces of data in your combobox see the below XAML
<ComboBox ...>
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding LocationId}"} />
<TextBlock Text=" - "/>
<TextBlock Text="{Binding LocationName}"} />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>

Resources