I have a ComboBox which lists the contact methods shown below. The ComboBox displays the correct values therefore the ItemSource Binding is working.
What i am trying to archive is that to display the selected contact method on application startup. I tried to bind the selected value to the ComboBox.Text attribute but i can't figure out how to set the filter.
This is my input data:
<Contact ShowsInterest="true">
<Name>Tester</Name>
<Lastname>Test</Lastname>
<ContactMethods>
<ContactMethod Selected="False">Phone</ContactMethod>
<ContactMethod Selected="False">Email</ContactMethod>
<ContactMethod Selected="True">Letter</ContactMethod>
<ContactMethod Selected="False">Mobile</ContactMethod>
</ContactMethods>
</Contact>
This is my ComboBox:
<ComboBox Name="combobox1"
ItemsSource="{Binding XPath=Contact/ContactMethods//*}"
Width="100" Height="25">
<ComboBox.Text>
<Binding XPath="Contact/ContactMethods//*[#Selected='true']"/>
</ComboBox.Text>
</ComboBox>
The XPath Expression should do the following: Display the Element under Contact/ContactMethods/ where selected equals true.
EDIT:
Even setting the Text Property directly won't work.
<ComboBox Name="combobox1"
ItemsSource="{Binding XPath=Contact/ContactMethods//*}"
Width="100" Height="25">
<ComboBox.Text>
Phone
</ComboBox.Text>
</ComboBox>
I guess i have to use the SelectedValue Property:
<ComboBox Name="combobox1"
ItemsSource="{Binding XPath=Contact/ContactMethods//*}"
Width="100" Height="25">
<ComboBox.SelectedValue>
Phone
</ComboBox.SelectedValue>
</ComboBox>
EDIT2:
This is the working solution, thanks to MikroDel
<ComboBox Name="combobox1"
ItemsSource="{Binding XPath=Contact/ContactMethods//*}"
Width="100" Height="25">
<ComboBox.SelectedValue>
<Binding XPath="Contact/ContactMethods/ContactMethod[#Selected='True']"/>
</ComboBox.SelectedValue>
</ComboBox>
This is the correct one :
<Binding XPath="Contact/ContactMethods/ContactMethod[#Selected='True']"/>
Related
Newbie question. In the following combobox, the drop-down list correctly displays the company name and phone number as per the DataTemplate. However, selecting an item from the drop-down (by mouse) resutls only in showing the object name:
Stargate_V.DataService.View_Small_Company
The selected company name and phone number is not shown. What am I doing wrong?
<ComboBox
ItemsSource="{Binding PrimaryInsurance.Companies}"
ItemTemplate="{StaticResource CompanyTemplate}"
IsEditable="True"
IsTextSearchEnabled="True"
Height="20" HorizontalAlignment="Left" Margin="375,235,0,0" VerticalAlignment="Top" Width="198" />
The CompanyTemplate is:
<DataTemplate x:Key="CompanyTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Companyname}" Width="240"/>
<TextBlock Text="|" Width="10"/>
<TextBlock Text="{Binding Phone}" Width="80" />
</StackPanel>
</DataTemplate>
TIA
The issue that you are having is the combination of displaying a complex type (i.e. Class) with a DataTemplate and your ComboBox has IsEditable set to true. When setting IsEditable to true the ComboBox doesn't know which property to use for searching so it just calls ToString on the object and displays the results. To fix this issue you need to set the TextSearch.TextPath to the property name on the object that you would like to use for searching. Once you do that it will display that property in the selection box instead of the result of ToString. Below is what your XAML should look like if you wanted to search on the Companyname property on your object.
<ComboBox
ItemsSource="{Binding PrimaryInsurance.Companies}"
ItemTemplate="{StaticResource CompanyTemplate}"
IsEditable="True"
IsTextSearchEnabled="True"
TextSearch.TextPath="Companyname"
Height="20" HorizontalAlignment="Left" Margin="375,235,0,0" VerticalAlignment="Top" Width="198" />
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}" />
I need to bind the value of the SelectedItem from the datagrid to:
SelectedItem of a combo box on the same page
Property in the viewmodel
In other words: when I select a row in the datagrid the value in the combobox should change and value of the meant above property should be also set to the value of the selected item of the datagrid.
I tried to use multibinding like this:
<DataGrid.SelectedItem>
<MultiBinding Converter="{StaticResource sapConverter}" >
<Binding Path="SelectedSap" Mode="TwoWay"/>
<Binding ElementName="cbSearchCompanyName" Path="SelectedItem" Mode="OneWay"/>
</MultiBinding>
</DataGrid.SelectedItem>
the SelectedSap here is that property, that I want to update. But when I look at the values() in the converter, value(0) corresponding to the SelectedSap is always Nothing and as a result the property doesn't change as I want.
The binding with the combo works fine.
I try to test it without multibinding. I mean, I don't care about the combo, I'm just changing the value of the property. Like this:
<DataGrid.SelectedItem>
<Binding Path="SelectedSap" Mode="TwoWay"/>
</DataGrid.SelectedItem>
everything works fine.
Where is the trick and how should I implement the functionality I need?
Thank you.
I think there is another good way to accomplish your goals:
<DataGrid Name="dgResults" ItemsSource="{Binding Path=DataGridObj}"
SelectedItem="{Binding SelectedItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
Maybe your binding is wrong.
If you get your items in the grid, your ItemsSource is fine. Use the SelectedValue and set the SelectedValuePath to the column you want the data from.
Skip the multibinding and set the binding on the combobox to be set to the SelectedValue of the DataGrid.
<DataGrid Name="dgResults" ItemsSource="{Binding Path=DataGridObj}"
SelectedItem="{Binding SelectedItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
SelectedValue="{Binding SelectedValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
SelectedValuePath="ItemNoX"
Š¢hank u a lot! Both your answers gave me a hint. Actually I have to bind three controls together (imagine functionality "search item" - you have a combo "search by item.X", combo "search by item.Y" and a datagrid with items), that's why I was little confused and started with the multibinding. The things are much more easier. Here's my code that now works:
<StackPanel Orientation="Horizontal" Grid.Row="0" >
<Label Content="Search company by name:"/>
<ComboBox MinWidth="200" Width="Auto" Name="cbSearchCompanyName"
ItemsSource="{Binding CompanyList,Mode=TwoWay}"
IsSynchronizedWithCurrentItem="True"
DisplayMemberPath="CompanyName1"
SelectedValuePath="Sap"
SelectedItem="{Binding Path=SelectedSap, Mode=TwoWay}"
SelectedValue="{Binding Path=SelectedSap.Sap, Mode=TwoWay}"/>
<Label Content="by SAP number:" />
<ComboBox MinWidth="200" Width="Auto" Style="{StaticResource marginStyle}" Name="cbSearchCompanySap"
ItemsSource="{Binding CompanyList,Mode=TwoWay}"
IsSynchronizedWithCurrentItem="True"
DisplayMemberPath="Sap"
SelectedValuePath="Sap"
SelectedItem="{Binding Path=SelectedSap, Mode=TwoWay}"
SelectedValue="{Binding Path=SelectedSap.Sap, Mode=TwoWay}"/>
</StackPanel>
<ScrollViewer Grid.Row="1" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<DataGrid x:Name="CompanyList" AutoGenerateColumns="True"
ItemsSource="{Binding CompanyList,Mode=TwoWay}"
MaxWidth="950" Height="300" Margin="0 2 0 0">
<DataGrid.SelectedItem>
<Binding Path="SelectedSap" Mode="TwoWay"/>
</DataGrid.SelectedItem>
</DataGrid>
</ScrollViewer>
I want to add a unbound column to a a xamgrid but I want to get the value from a combox, the combobox is bound to channel object at runtime.
I tried adding the unbound column.
Tried:
<Binding Source="{StaticResource ChannelTemplate}" Path="SelectedItem.Content" />
But it doesn't seem to work
I want to bind the channelcode to the grid.
Grid,class code below.
<UI:BaseControl.Resources>
<DataTemplate x:Key="ChannelTemplate" >
<StackPanel Orientation="Horizontal" >
<TextBlock Margin="2" Text="{Binding Path=ChannelName}"/>
</StackPanel>
</DataTemplate>
</UI:BaseControl.Resources>
<ComboBox Name="CboChannel" Margin="59,6,0,0" Height="22" Width="200" VerticalAlignment="Top" HorizontalAlignment="Left" ItemTemplate="{StaticResource ChannelTemplate}" >
</ComboBox>
<ig:XamGrid Name="grdInventory" ColumnWidth="auto" ....
<ig:XamGrid.Columns>
<ig:UnboundColumn Key="Channel">
<ig:UnboundColumn.ItemTemplate>
<DataTemplate >
<TextBlock >
<TextBlock.Text >
<Binding Source="{StaticResource ChannelTemplate}" Path="SelectedItem.Content" />
</TextBlock.Text>
</TextBlock>
</DataTemplate>
</ig:UnboundColumn.ItemTemplate>
</ig:UnboundColumn>
</ig:XamGrid.Columns>
</ig:XamGrid>
Code:
Public Class Channel
Implements IDisposable
<DataMember(IsRequired:=True)>
Public Property ChannelID As Long
<DataMember()>
Public Property ChannelDescription As String
<DataMember()>
Public Property ChannelName As String
<DataMember()>
Public Property ChannelCode As String
End Class
Thanks
J
You could try using a DataContext pattern so that your unbound column and combobox selected item are both bound to the same value. For example (I'm using the standard data grid here):
1) Create a DataContextProxy class based on this article: http://weblogs.asp.net/dwahlin/archive/2009/08/20/creating-a-silverlight-datacontext-proxy-to-simplify-data-binding-in-nested-controls.aspx
2) Create a static resource to the DataContextProxy on the page that contains the grid and combo e.g.
<UserControl.Resources>
<Silverlight:DataContextProxy x:Key="Proxy"></Silverlight:DataContextProxy>
</UserControl.Resources>
3) Bind the SelectedValue property of your combo to an exposed property on your VM e.g.
<ComboBox Height="23"
HorizontalAlignment="Left"
SelectedValue="{Binding TestProperty, Mode=TwoWay}"
SelectedValuePath="Content"
Margin="126,54,0,0" x:Name="comboBox1"
VerticalAlignment="Top" Width="120" DisplayMemberPath="Content">
<ComboBox.Items>
<ComboBoxItem x:Name="x" Content="test2"></ComboBoxItem>
<ComboBoxItem x:Name="x2" Content="test"></ComboBoxItem>
</ComboBox.Items>
</ComboBox>
4) Bind the grid column template to the same VM property e.g.
<sdk:DataGrid AutoGenerateColumns="True"
Height="120"
HorizontalAlignment="Left"
Margin="155,153,0,0"
Name="dataGrid1"
VerticalAlignment="Top" Width="120">
<sdk:DataGrid.Columns>
<sdk:DataGridTemplateColumn Header="Test">
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Mode=OneWay,Source={StaticResource Proxy},Path=DataSource.TestProperty}">
</TextBlock>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>
</sdk:DataGrid.Columns>
</sdk:DataGrid>
This worked for me when I knocked up a quick test app. The DataGridTemplateColumn stays in sync with the selected combobox item.
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>