DataGrid: Partial binding - wpf

Let me try and state the simplest version of the question:
Can I have an UNBOUND dropdown-type column in my BOUND DataGrid?
Here is an example if the above statement is too abstract to understand:
A DataGrid named dgStudents that is bound to a DataTable named dtStudents, showing a few of the columns of the table, say Name, Age and City, all being simple DataGridTextColumns. I want to add a 4th column to my grid named say FavSports that is a simple dropdown type column, bound to a static list of common sports. The most important thing here is that (unlike other 3 columns) this dropdown column DOES NOT have a corresponding column in the DataTable. It'll just be required for the life of the DataGrid, so I'm not storing it anywhere.
I have tried the following:
<DataGridComboBoxColumn ItemsSource="{StaticResource Sports}">
where Sports is an array defined right within XAML:
<x:Array x:Key="Sports" Type="sys:String">
<sys:String>Football</sys:String>
<sys:String>Hockey</sys:String>
<sys:String>Tennis</sys:String>
</x:Array>
Can't get this to work for the life of me. The dropdown does display and user can select a value out of it that does show after user moves to another cell, but that's about it. After user comes back to that cell, the drop-down appears empty and even if user then leaves the cell without clicking the dropdown, the previous value is gone.

If you just want to bind to your StaticResource, try this:
<DataGridComboBoxColumn ItemsSource="{Binding Source={StaticResource Sports}}">

Related

Access to name of an object in combobox in WPF

I have a ComboBox in WPF, and a table (Trainer) in my DataBase. They are linked together as following:
comboTrain.ItemsSource = (from t in ctx.Trainers select t).ToList<Trainer>();
Also, I bind it in xaml as following:
<ComboBox x:Name="comboTrain" ItemsSource="{Binding TrainerCollect}"
DisplayMemberPath="Name" SelectedValuePath="TrainerId"/>
So, when I run the application, I see the name of all trainers in ComboBox. Now, I want to show only the name of trainer who is selected in ComboBox.
How can I do that?
I found a solution for my question: with using "comboTrain.Text" I could get the selected item as a string.

WPF DataGridComboBox column with static list of Tuples or KeyValuePairs defined in XAML?

It's possible to declare the list of combobox items in a DataGridComboBox column in the xaml using a column definition such as
<DataGridComboBoxColumn Header="Gender"
SelectedItemBinding="{Binding Gender, UpdateSourceTrigger=PropertyChanged}">
<DataGridComboBoxColumn.ItemsSource>
<CompositeCollection>
<system:String>M</system:String>
<system:String>F</system:String>
</CompositeCollection>
</DataGridComboBoxColumn.ItemsSource>
</DataGridComboBoxColumn>
This is fine if the values in the binding match what we want to display on screen. It's also possible to bind ItemsSource to a Dictionary in code and use SelectedValuePath and DisplayMemberPath to display one set of values (e.g. Male, Female) whilst using another set of values (e.g. M, F) in the backing store.
Is it possible, without writing a utility class to represent the key-value pair, to define the latter type of items list entirely in XAML? I've tried putting a Dictionary in there instead of the CompositeCollection, and defining the CompositeCollection to contain elements of KeyValuePair or Tuple but without success- when using the correct namespaces, Dictionary and Tuple simply aren't recognised, and KeyValuePair actually shows in the autocomplete as KeyValuePair'2 but still isn't recognised when selected (neither is KeyValuePair.)

ComboBox has extra space at the bottom

I have a ComboBox that shows empty space below its values. See picture below.
The data in the view model is set in a button click handler. When I set the values in the initialization of the view model the ComboBox is fine. When I try to create a small example the ComboBox also has the expected size. It seems it depends somehow on the context where I set the values in the view model but I cannot figure out. I hope someone can give me a hint.
Code in the view model
Repositories.Clear();
Repositories.Add("One");
Repositories.Add("Two");
Repositories.Add("Three");
SelectedRepository = "One";
Code in XMAL
<ComboBox MinWidth="150"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
IsEnabled="{Binding CT.Connected}"
ItemsSource="{Binding CT.Repositories,
UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding CT.SelectedRepository}"/>
The ItemsSource you are binding to needs to be an ObservableCollection. The ComboBox will display the initial blank space if you bind the ItemsSource to any enumerable type that doesn't raise property changed when its items change.
When I try to create a small example the ComboBox has the expected size.
By that logic it maybe not the combobox, but the data which is in the list. Can you verify that there are not 8 items where the textual value to display is empty for the last four items or so?
Or
Maybe a style is causing the extra space. Try removing the style from the combobox such as this
<ComboBox Style="{x:Null}"/>
and see if it has any effect to the visual result.
Or
Also how about not setting the data and see if the drop down has the same size?

Wpf datagrid doesn't show current cell selection when focus is lost

I have a WPF DataDrid where I'm using a combination of row selection and cell selection.
That is - I want full row select and an indication of the currently selected simultaneously. That is working fine if I use SelectionUnit=FullRow and SelectionMode=Single and combined with a thicker cell border this looks pretty good.
The problem is that when the DataGrid loses focus only the row selection stays visible, the CurrentCell property is reset and there is no way for the user to identify which cell is selected. This also happens if the user is interacting with the content in the RowDetails panel.
Is there any way to change the behavior of the current cell so that it shows the SelectedCell even when not focused?
Do not use the CurrentCell to track the selected row. Use the property SelectedItem instead.
Something like this:
<DataGrid ItemsSource="{Binding MyItems}" SelectedItem="{Binding MySelectedItem}">
...
</DataGrid>

How do I bind a lookup combobox?

My WPF4 combobox dropdown list is incorrectly displaying the class name of my EF4 entity. Here is the relevant XAML:
<Window.Resources>
<CollectionViewSource x:Key="myEntitiesViewSource"/>
</Window.Resources>
<ComboBox ItemsSource="{Binding Source={StaticResource myEntitiesViewSource}}" DisplayMemberPath="CategoryDescription" SelectedValuePath="CategoryID" />
Here is the code in my Window_Loaded event:
var categoryList = from p in _context.Categories
orderby p.CategoryNumber
select p;
System.Windows.Data.CollectionViewSource myEntitiesViewSource = ((System.Windows.Data.CollectionViewSource)(this.FindResource("myEntitiesViewSource")));
// Load data by setting the CollectionViewSource.Source property:
myEntitiesViewSource.Source = categoryList;
My database has a many to many relationship between Projects and Categories with a join table called ProjectCategories. The Categories entity was automagically created as a single entity to represent two database tables:
1) the lookup table of Categories containing an ID, CategoryDescription and CategoryNumber and
2) the join table ProjectCategories containing only two fields - the IDs from the tables Projects and Categories. The entity model lives in a separate project from my WPF window.
My goal is to allow the user to select a CategoryDescription from the dropdown list, then click an Add Category button to add the selected Category to a separate list of ProjectCategories. With the current code I see the correct CategoryDescription in the combobox text area but the dropdown list displays only the entity class name Categories (preceded by it's namespace) multiple times!
How do I make this simple lookup combobox bind correctly and display a list of CategoryDescriptions and a SelectedValue of CategoryID? Note: I'd accept a code only approach leaving out the CollectionViewSource in XAML if it's possible.
Thanks!
Nevermind. I asked this question and have answered it myself. There was nothing wrong with my code or XAML. The problem was caused by the use of a third party theme to style my controls. Once I removed the theme the combobox binding problem went away. For more details see this post.
What about something like this?
<ComboBox ItemsSource="{Binding Categories}"
SelectedItem="{Binding Category}" DisplayMemberPath="Description" />
Instead of using a Selected Value, I would store the whole object. The selected value approach is old ASP style for my taste.
SelectedItem="{Binding Category}" is your Category object. Basically it has stored the selected item of the ComboBox.
When the user clicks a button for example, you can fire a Command from the ViewModel and you will have the corresponding selected Category object.

Resources