This is my enum class
public enum testservice
{
New,
NBG
}
I have used below ref in the xaml
<Grid.Resources>
<ObjectDataProvider x:Key="dataFromEnum" MethodName="GetValues" ObjectType="{x:Type System:Enum}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="local:testService"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</Grid.Resources>
and i set the itemsource of combobox as shown below
ItemsSource="{Binding Source={StaticResource dataFromEnum}}"
But I dont know how to set the selecteditem of the combo ?
Also once everything is set, how to retrieve the selected item back from the code. Suppose i chose "New" value from the combo and saved in the DB. Next time when i open the window, how do i display back the "New" in the combo box ??
You may use the property SelectedItem of the ComboBox to get and set the required value ("New" as you mentioned in above description).
Related
I have a ComboBox inside a UserControl. I use the UserControl in a Window with a DataGrid: the UserControl DataContext is the DataGrid SelectedItem. The ComboBox inside the UserControl is bound to the "ID" field of the SelectedItem through the SelectedValue Property. To achieve that I programmed a DependencyProperty in the UserControl like this
Public Shared SelectedValueProperty As DependencyProperty = _
DependencyProperty.Register("SelectedValue", GetType(Object), GetType(ucEditCombo))
Public Property SelectedValue() As Object
Get
Return CType(GetValue(SelectedValueProperty), Object)
End Get
Set(ByVal value As Object)
SetCurrentValue(SelectedValueProperty, value)
End Set
End Property
and bound the ComboBox SelectedValue Property to the UserControl SelectedValue Property in XAML:
<ComboBox SelectedValuePath="{Binding ElementName=EditCombo,Path=SelectedValuePath}"
DisplayMemberPath="{Binding ElementName=EditCombo,Path=DisplayMemberPath}"
ItemsSource="{Binding ElementName=EditCombo,Path=ItemsSource}"
SelectedValue="{Binding ElementName=EditCombo,Path=SelectedValue,Mode=TwoWay}"
Visibility="{Binding ElementName=EditCombo,Path=ComboVisibility}"
Name="cmb"/>
(EditCombo is the x:Name I give to the UserControl in XAML).
Running the application I not the following:
If I change the DataGrid selection, then the ComboBox displayed value changes correctly.
As soon as I change the ComboBox selected value directly on the control, the value in the DataGrid doesn't get updated AND the ComboBox isn't bound to the DataGrid SelectedItem any longer.
The problem regarding the update of the original DataGrid SelectedItem is not apparent, although I believe it is to do with the bindings on the ComboBox. I would need to see the Window xaml and the UserControl's code behind to be sure.
I attempted to reproduce the problem with an example, but I was unable to. So to speed up your movement forward, I have posted the example below.
Assumption: The UserControl is attempting to modify properties of the object bound to the SelectedValue DependencyProperty, not attempting to replace the object. If the assumption is incorrect, update the question with the extra code that is relevant to the problem and I will attempt to update my answer.
Firstly, I have a model that I use when creating code for StackOverflow questions called ItemModel.
Public Class ItemModel
Public Property Id as Guid
Public Property Text as String
End Class
and on the Window, I have created an ObservableCollection(Of ItemModel) property called Items. It contains 3 items with each item having its Text property set to one of the values "One", "Two" or "Three". The Id of each item is set to a new guid.
So, my main window xaml looks like
<Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:this="clr-namespace:StackOverflow._20798974"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="MainWindow" Height="350" Width="525">
<DockPanel>
<StackPanel Orientation="Horizontal" DockPanel.Dock="Bottom">
<this:ucEditCombo SelectedValue="{Binding ElementName=MyGrid, Path=SelectedItem}" />
</StackPanel>
<DataGrid x:Name="MyGrid" ItemsSource="{Binding Path=Items}" AutoGenerateColumns="False" >
<DataGrid.Columns>
<DataGridTextColumn Header="Id" Binding="{Binding Id}"/>
<DataGridTextColumn Header="Text" Binding="{Binding Text}" Width="*"/>
</DataGrid.Columns>
</DataGrid>
</DockPanel>
</Window>
The code behind of the ucEditCombo UserControl contains the DependencyProperty you have defined in the question above and an ObservableCollection(Of String) which is populated with the values "One", "Two", "Three" and "Four".
The xaml for the user control is
<UserControl x:Class="ucEditCombo" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:this="clr-namespace:StackOverflow._20798974"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type this:ucEditCombo}}}">
<ComboBox ItemsSource="{Binding Path=Items}" SelectedValue="{Binding Path=SelectedValue.Text}" />
</Grid>
</UserControl>
The above example allows me to selected a DataGrid item and have the Text property of that item immediately appear in the ComboBox. It also allows the selection of a different value in the ComboBox and have that value updated in the DataGrid.
Points to note.
Setting the DataContext of the Control in the Controls constructor will break the SelectedItem binding on the Window. To get around this, I have set the DataContext on the first content element of the UserControl (a Grid element).
The DataContext is set to the UserControl itself, simplifying some of the bindings on the Combobox.
As we are modifying a property of a DependencyProperty, a lot of the WPF binding subsystem notifications are taken care of for us.
The default binding mode for SelectedValue and SelectedItem is TwoWay.
I hope this helps.
I'll try to give a bit more details of this question
In a WPF application, on the left side of 'mainwindow' I have a UserControl containing a listBox, like this
<UserControl.Resources>
<ObjectDataProvider x:Key="viewModel" ObjectType="{x:Type vm:TemplateListViewModel}"/>
</UserControl.Resources>
<StackPanel>
<ListBox Height="Auto" Name="TemplateList" ItemsSource="{Binding Source={StaticResource viewModel}, Path=TemplateNames}"
</StackPanel>
As shown, listbox items are fetched from a xml file via viewModel.
Now I have another usercontrol2 containing a Label to echo the selection from "TemplateList".
Also under this label I have another usercontrol3 containing a datagrid, which data will be fetched from a xml file based on the label, or the selection from the listbox on the left side of the window through usercontrol3's viewmodel.
So the question is how to pass the "SelectedItem" or "SelectedIndex" to viewModel of the Label and datagrid?
I know it works when I bind a label to a listbox with 'elementName' and Path to 'SelectedItem'. Now I couldn't figure out how to do with usercontrols and 'ObjectDataProvider'. I tried as suggested below couldn't get it to work out. So far for usercontrol2, if I use the same ObjectDataProvider as the above, I can get this label to work as
<Label Name="TemplateNameLabel" Content="{Binding Source={StaticResource viewModel}, Path=TemplateNames[0]}" />
Where 'TemplateNames' if of type 'XmlNodeList' because it was read from xml file. But I really want is something like
<Label Name="TemplateNameLabel" Content="{Binding Source={StaticResource viewModel}, Path=TemplateNames[SelectedIndex]}" />
Can this be done without any command, just like binding to 'elementname' without usercontrol involved?
Thanks.
I've removed not important properties to highlight the main:
<ListBox Name="TemplateList" ItemsSource="{Binding Source={StaticResource viewModel}, Path=TemplateNames}" SelectedItem="{Binding Path=SelectedTemplate, Mode=OneWayToSource}" />
Note, that you will need SelectedTemplate property with public setter of type TemplateName - the same type that is used for single element in the TemplateNames collection in the ViewModel. In that setter you could pass the value to whatever other view-models you need.
Is there some way in WPF to get the same functionality DataTemplateSelector gives you, but for UserControls?
Say I have a StackView to which I want to bind an IEnumerable of objects. What I'd like to do is somehow have a mapping that, for each object type in the bound IEnumerable, looks at the object type and determines what UserControl to add to the StackView.
So, given three classes:
public class House : Building{}
public class Apartment : Building{}
public class Tent : Building{}
where each class inherits from Building and has its own defined UserControl, I'd like to set DataContext to an IEnumerable<Building> and somehow get the StackView to populate its set of children with the type-specific UserControl.
I'd like to do this with as little code behind as possible. The more data binding and XAML duct tape the better.
You can use complex user controls in a DataTemplate; just declare the DataTemplate as your UserControl.
Example:
<Window x:Class="WpfApplication4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication4"
Title="MainWindow" Height="300" Width="300" Name="UI" >
<Window.Resources>
<DataTemplate DataType="{x:Type local:House}" >
<local:HouseUserControl DataContext="{Binding}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Apartment}">
<local:ApartmentUserControl DataContext="{Binding}"/>
</DataTemplate>
</Window.Resources>
<Grid>
<ListBox ItemsSource="{Binding ElementName=UI, Path=ListOfBuildings}" />
</Grid>
</Window>
I'm not sure I see the problem. Just create DataTemplates for each type in your resources somewhere and WPF will use them automatically to render each type.
I got two Comboboxes and both of them have binding with the same Source.
<ComboBox ItemsSource="{Binding Source={StaticResource UsersViewSource}}"
And when I change something in the first one, it reflects also to the second one. And I dunno how to keep their SelectedItem values separately, using the same ItemsSource.
The IsSynchronizedWithCurrentItem property should be set to False:
true if the SelectedItem is always
synchronized with the current item in
the ItemCollection; false if the
SelectedItem is never synchronized
with the current item; null if the
SelectedItem is synchronized with the
current item only if the Selector uses
a CollectionView. The default value is
null.
Here's a sample:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
<x:Array x:Key="myStrings" Type="sys:String">
<sys:String>one</sys:String>
<sys:String>two</sys:String>
<sys:String>three</sys:String>
<sys:String>four</sys:String>
<sys:String>five</sys:String>
</x:Array>
</Page.Resources>
<StackPanel Width="200">
<ComboBox IsSynchronizedWithCurrentItem="False" Margin="25"
ItemsSource="{Binding Source={StaticResource myStrings}}" />
<ComboBox IsSynchronizedWithCurrentItem="False" Margin="25"
ItemsSource="{Binding Source={StaticResource myStrings}}" />
</StackPanel>
</Page>
You just need to set the IsSynchronizedWithCurrentItem property to false (by default it's null)
I'd guess (from the name of your binding) that the reason this is happening is that you're binding to a CollectionViewSource (that wraps a collection). This class is a proxy that WPF uses that includes (amongst other things) the selected item of a collection. Obviously if you're sharing this collection between two comboboxes, you're also sharing the selected item.
If you set ItemsSource to something that's not a CollectionViewSource, the control will automatically wrap it in one. So, my suggestion would be to bind directly to a collection instead of wrapping in a CollectionViewSource - or, alternatively, create two CollectionViewSource instances, one for each ComboBox.
You can separately bind the SelectedItem property for each combo box separately.
i.e.
SelectedItem={Binding SelectedItem1}
This way when each one's item gets set, it gets stored into a different place.
I have a MainWindow.xaml (which consists of a TabControl) and a few UserControls (which are loaded into the TabItems).
One particular UserControl has a WPFToolkit DataGrid with custom columns (not auto-generated). One of these columns is a ComboBox-type column that binds to a property in my model called "Status". I also have an Enum for Status called "FollowUpStatus". This ComboBox column is declared as follows:
<WpfTK:DataGridComboBoxColumn
Header="Status"
SelectedItemBinding="{Binding Status}"
ItemsSource="{Binding Source={StaticResource FollowUpStatusProvider}}" />
The FollowUpStatusProvider is an ObjectDataProvider declared as follows at the application resources level - visible to both MainWindow and all UserControls:
<ObjectDataProvider x:Key="FollowUpStatusProvider"
MethodName="GetValues" ObjectType="{x:Type DAL:FollowUpStatus}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="DAL:FollowUpStatus"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
It all works fine at run-time. At design time, from MyUserControl.xaml, the designer renders it ok. But my MainWindow complains it cannot "create an instance of type 'MyUserControl'". The code that's causing MainWindow to choke is the assignment to ItemsSource in the ComboBox column:
... ItemsSource="{Binding Source={StaticResource FollowUpStatusProvider}}" ...
If I remove this assignment, it all works as expected.
Can somebody help me understand why and how to fix it?
Thanks!
Have you tried
... ItemsSource="{StaticResource FollowUpStatusProvider}"