I have a class called Contact that has 2 string properties: "Name" and "PhoneNumber".
My ViewModel has an observable collection of these contacts and there is a ComboBox that has it's ItemsSource bound to this collection .
I have a WPF Grid whose DataContext is set to the ComboBox's SelectedItem property. This Grid has a BindingGroup that contains a ValidationRule to validate the text properties of my "contact" class.
This is my Grid:
<Grid x:Name="ContainerGrid" Grid.Column="0"
Background="Transparent"
LostFocus="ContainerGrid_LostFocus"
ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}">
<Grid.BindingGroup>
<BindingGroup x:Name="TextInputBindingGroup" SharesProposedValues="True">
<BindingGroup.ValidationRules>
<local:TextInputValidationRule />
</BindingGroup.ValidationRules>
</BindingGroup>
</Grid.BindingGroup>
<StackPanel>
<TextBlock Text="Name:" />
<TextBox x:Name="PersonName" Text="{Binding Path=PersonName, ValidatesOnExceptions=True}" />
</StackPanel>
<StackPanel>
<TextBlock Text="Phone Number:" />
<TextBox x:Name="PhoneNumber" Text="{Binding Path=PhoneNumber, ValidatesOnExceptions=True}" />
</StackPanel>
</Grid>
If the data for the contact was invalid (the name and/or phone number was missing) the grid containing the elements for editing these properties is highlighted in red and it's tool tip is set to the first error.
If I then delete the invalid Contact, the grid remains outlined in red with the tool tip displaying the error for the item that was deleted even though the grid is now displaying another, valid item.
How do I clear the errors shown in the grid?
Thanks,
-Frinny
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 app that displays a Label in read-only mode and a ComboBox in edit mode. When the user clicks the 'Edit' button, the label is hidden and the ComboBox becomes visible (using a BooleanToVisibilityConverter).
The ItemsSource of the ComboBox is set to its lookup table (via auditorsViewSource), and the DataContext of the TextBox is set to the parent table (via auditStatementsViewSource).
Here is my xaml:
<!-- Auditor info -->
<StackPanel Orientation="Horizontal" DataContext="{StaticResource auditStatementsViewSource}">
<StackPanel Orientation="Horizontal" >
<Label Content="Auditor:" Name="lblAuditor" />
<!-- readonly data -->
<StackPanel Style="{StaticResource VisibleWhenReadOnly}">
<TextBox Name="txtAuditor" >
<TextBox.Text>
<MultiBinding StringFormat="{}{0} {1}">
<Binding Path="Auditor.GivenName"/>
<Binding Path="Auditor.Surname"/>
</MultiBinding>
</TextBox.Text>
</TextBox>
</StackPanel>
<!-- editable data -->
<StackPanel Style="{StaticResource CollapsedWhenReadOnly}" >
<ComboBox x:Name="cboAuditor" IsSynchronizedWithCurrentItem="True" DisplayMemberPath="Surname"
ItemsSource="{Binding Source={StaticResource auditorsViewSource}}"
SelectedItem="{Binding Source=txtAuditor, Path=Auditor.Surname, Mode=TwoWay}" />
</StackPanel>
</StackPanel>
</StackPanel>
The ComboBox displays the items from the base (auditors) table correctly, but displays the first record in the table (according to the ORDER BY clause). How do I get it to initially show the item from the current (auditStatements) record, (ie, the Auditor that was being displayed by the readonly label), preferably in xaml?
Normally, Binding to the ComboBox.SelectedItem property works best if you are Binding an actual element from the collection that is data bound to the ComboBox.ItemsSource property. As you are not using an actual element from the ItemsSource collection, you might have to do things somewhat differently.
On possible solution is for you to use the SelectedValue, SelectedValuePath and DisplayMemberPath properties instead. Please see the How to: Use SelectedValue, SelectedValuePath, and SelectedItem page on MSDN for full details on using this method to access the selected item.
I have a view and ViewModel that are working perfectly. I have recently added an AutocompleteBox (found in the WPF Toolkit) which allows users to quickly look up an item.
My view is as such:
An ItemsControl containing my CollectionViewSource named People. Generating perfectly
An AutocompleteBox where the dropdown shows only the items containing the values the user is typing in the AutocompleteBox. Works well. If I type John, all of the people in my CollectionViewSource named People with the word John in the name appear in the dropdown.
My issue is: how do I filter my ItemsControl when the user selects the item he wishes to see from the Dropdown?
My code so far in XAML to bind the data:
<toolkit:AutoCompleteBox Height="25" Width="400"
Foreground="AliceBlue"
ItemsSource="{Binding People.View}"
ValueMemberPath="Name"
Text="{Binding Name}"
IsTextCompletionEnabled="True"
FilterMode="Contains"
Background="#303030">
<toolkit:AutoCompleteBox.ItemTemplate>
<DataTemplate>
<Grid Width="360" HorizontalAlignment="Left">
<StackPanel Orientation="Vertical" HorizontalAlignment="Left"
VerticalAlignment="Top" Width="300">
<TextBlock Text="{Binding Name}" FontWeight="SemiBold" Foreground="#25A0DA"
FontSize="14" Width="300"/>
<TextBlock Text="{Binding Status}" FontWeight="Normal" Foreground="White"
FontSize="10" Width="300"/>
</StackPanel>
</Grid>
</DataTemplate>
</toolkit:AutoCompleteBox.ItemTemplate>
</toolkit:AutoCompleteBox>
<ItemsControl x:Name="tStack" Grid.Column="0" Grid.Row="1"
ItemsSource="{Binding People.View}"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
BorderThickness="0.5">
</ItemsControl>
The itemsControl is styled and the format of the items inside it are also templated/styled but far too long and unconstructive to post here.
From the Name property setter in your viewmodel to which toolkit:AutoCompleteBox.Text is bound, you will have to filter the ObservableCollection backing your Collectionview i,e ItemsSource of your ItemsControl.
If you have your Collectionsource with you then you can have filter applied to it like below:
ICollectionView _peopleView = CollectionViewSource.GetDefaultView(peoples);
_peopleView .Filter = PeopleFilter
private bool PeopleFilter(object item)
{
People people= item as People;
return people.Name.Contains( _filterString ); //Here filter string will be your Name prperty value
}
From Setter of name property you will hav to call _peopleView .Refresh(); to apply the filter
Thanks
I'm new to WPF, but am pretty familiar with binding list box controls to observable collections in the view model.
In my current project we have a ListBox that is used for navigating to different pages in a frame box. I want to add some display information to the first ListBoxItem to show which object (in this case, the Scenario) is being worked on (it is selected in a previous frame that visible in the subsequent frames). The ListBox itself is using a static list defined in the xaml, so it isn't bound to anything in the ViewModel. The CurrentScenario is a property on the ViewModel. I was able to add a Label to the same window that contains this ListBox and successfully bind CurrentScenario.Id to its content, and it updated correctly, so I know that the path in the Binding statement should resolve correctly.
<ListBox
Style="{StaticResource FunctionBackground}"
IsSynchronizedWithCurrentItem="True"
>
<ListBoxItem Style="{StaticResource FunctionListBoxItemStyle}">
<ListBoxItem.ContentTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="Scenario" />
<TextBlock Grid.Row="1" Text="{Binding Path=CurrentScenario.Id}"/>
</Grid>
</DataTemplate>
</ListBoxItem.ContentTemplate>
</ListBoxItem>
<ListBoxItem Style="{StaticResource FunctionListBoxItemStyle}" >Parameter</ListBoxItem>
<ListBoxItem Style="{StaticResource FunctionListBoxItemStyle}" >Run</ListBoxItem>
<ListBoxItem Style="{StaticResource FunctionListBoxItemStyle}" >Results</ListBoxItem>
</ListBox>
When I try to add this extra information to the listbox item, from what I can tell, the list box item has an empty text block below the text block with the word "Scenario." I can't figure out why the empty text box content is not showing the value of the bound property. When I put a normal string in the Text property of the second text block, it shows up correctly.
I imagine that either ListBoxItem content is only set up be bound to properties related to the ItemSource, and so it ignores attempts to bind to other things, or maybe there is something fundamental in WPF that I am missing. Or both...
Thanks if anyone has any ideas!
So if property CurrentScenario is in ViewModel you can use RelativeSource to binding to this property.
...
<TextBlock Grid.Row="0" Text="Scenario" />
<TextBlock Grid.Row="1" Text="{Binding Path=DataContext.CurrentScenario.Id, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"/>
...
I have an XML file with these nodes:
<Product>
<Name>...
<Color>...
<Price>...
</Product>
I have a listbox that displays all the Name's in the XML file like this:
<ListBox Name="listBox1" ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<DockPanel >
<TextBlock Text = "{Binding Name}" />
</DockPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
When an item in the listbox is selected, I want to display the selected product's Color and Price on 2 label controls.
How do I bind the Color and Price to the selected Name?
This means I need to get the Color and Price info from the XML file because the listbox has only the Name.
Thanks.
The SelectedItem will be the whole item, with all three elements, so something like this should do:
<StackPanel DataContext="{Binding SelectedItem, ElementName=listBox1}">
<TextBlock Text="{Binding XPath=Color}" />
<TextBlock Text="{Binding XPath=Price}" />
</StackPanel>
(Could use Binding.StringFormat to prepend a label, also the Label control itself is for labelling things, not displaying text)