I have a datagrid which has a column of comboboxes. The data grid itemssource is a collection of UserInfo objects.
Here's the definition of UserInfo class:
public class UserInfo
{
public string User { get; set; }
public UserRole Role { get; set; }
}
public enum UserRole
{
None = 0,
Administrator = 1,
Reviewer = 2,
}
When I have the collection, I assign it to the datagrid:
private void svc_GetAllUsersCompleted(object sender, ServiceReference1.GetAllUsersCompletedEventArgs args)
{
ObservableCollection<UserInfo> users = args.Result;
UsersPage.dataGrid1.ItemsSource = users;
}
Here's the xaml of the datagrid:
<data:DataGrid Margin="5,25,5,17" AutoGenerateColumns="False" AllowDrop="True" Name="dataGrid1" SelectionMode="Single" UseLayoutRounding="True" SelectionChanged="dataGrid1_SelectionChanged" Grid.RowSpan="2" Grid.ColumnSpan="2" Grid.Row="1" ItemsSource="{Binding}" >
<data:DataGrid.Resources>
<DataTemplate x:Key="UserRoleTemplate">
<Border BorderThickness="0,0,0,0" BorderBrush="#6FBDE8">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ComboBox Name="cmbUserRoleTypes" VerticalAlignment="Center" Grid.Column="0" Loaded="cmbUserRoleTypes_Loaded" SelectedIndex="0" ItemsSource="{Binding GetListOfRoles,Source={StaticResource rList}}" SelectedValue="{Binding Role, Mode=TwoWay}" ></ComboBox>
</Grid>
</Border>
</DataTemplate>
<DataTemplate x:Key="UserNameTemplate">
<Border BorderThickness="0,0,0,0" BorderBrush="#6FBDE8">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Name="txtUserName" VerticalAlignment="Center" Grid.Column="0" Loaded="cmbUserRoleTypes_Loaded" Text="{Binding Path=Name}" ></TextBlock>
</Grid>
</Border>
</DataTemplate>
</data:DataGrid.Resources>
<data:DataGrid.Columns>
<data:DataGridTextColumn Header="User Name" Width="200"
Binding="{Binding User}" />
<data:DataGridTemplateColumn Header="User Role" Width="200"
CellTemplate="{StaticResource UserRoleTemplate}" />
<!--<data:DataGridTextColumn Header="Assigned Issues" />-->
</data:DataGrid.Columns>
</data:开发者_运维技巧DataGrid>
The combo is filled using a collection from a class that has all the users roles:here's the xaml:
<UserControl.Resources>
<local:RolesTypes x:Key="rList">
</local:RolesTypes>
</UserControl:Resources>
And here's the class that has the collection:
public class RolesTypes
{
public List<string> GetListOfRoles
{
get
{
List<string> RolesList = new List<string>();
RolesList.Add("administrator");
RolesList.Add("reviewer");
return RolesList;
}
}
}
My problem is: The combo fills fine with the list of roles, but when I receive the usersinfo collection, I want each user to have its role selected in its matching combo and it doesn't happen. no role is selected in the combo, although the users roles DO exist in the list of roles . Any ideas?
CAVEAT: this populates the grid with a combobox and sets the combobox to the users' role. It's done in code behind, which I think violates all the MVVM principals, but I couldn't get binding to work. (Maybe some binding expert could modify this) That said, if you go with it you should probably attach a handler to the combobox to update you're user's role when the combo box is changed. Hope this helps and good luck!
REVISED cmbUserRoleTypes_Loaded to populate combo box, and removed converter code. Note that the different role values are hard coded, you probably want to make that generic.
REVISED to include combo box, sorry was rushing to finish before I had to leave and didn't re-read your post. I don't really like that it has to set the combo box in code-behind, it seems like there should be some way to data bind it. NOTE: I'm having trouble with binding the combo box selection to the user record, but at least this gets the populated combo boxes in there. Hope it helps.
Here is the xaml
<UserControl xmlns:data="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" x:Class="StackOverflowProblems.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:StackOverflowProblems"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Button Content="Populate users" Click="btn_Click" HorizontalAlignment="Left"></Button>
<StackPanel Grid.Row="1" Orientation="Horizontal">
<data:Label Content="Roles:"/>
<ComboBox VerticalAlignment="Center" Name="myComboBox" ></ComboBox>
</StackPanel>
<Grid Grid.Row="2" x:Name="LayoutRoot" Background="White">
<data:DataGrid Margin="5,25,5,17" AutoGenerateColumns="False" AllowDrop="True" Name="dataGrid1" SelectionMode="Single" UseLayoutRounding="True" SelectionChanged="dataGrid1_SelectionChanged" Grid.RowSpan="2" Grid.ColumnSpan="2" Grid.Row="1" ItemsSource="{Binding}" >
<data:DataGrid.Resources>
<DataTemplate x:Key="UserRoleTemplate">
<Border BorderThickness="0,0,0,0" BorderBrush="#6FBDE8">
<ComboBox VerticalAlignment="Center" Loaded="cmbUserRoleTypes_Loaded" >
</ComboBox>
</Border>
</DataTemplate>
<DataTemplate x:Key="UserNameTemplate">
<Border BorderThickness="0,0,0,0" BorderBrush="#6FBDE8">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Name="txtUserName" VerticalAlignment="Center" Grid.Column="0" Loaded="cmbUserRoleTypes_Loaded" Text="{Binding Path=Name}" ></TextBlock>
</Grid>
</Border>
</DataTemplate>
</data:DataGrid.Resources>
<data:DataGrid.Columns>
<data:DataGridTextColumn Header="User Name" Width="200" Binding="{Binding User}" />
<data:DataGridTemplateColumn Header="User Role" Width="200" CellTemplate="{StaticResource UserRoleTemplate}" />
</data:DataGrid.Columns>
</data:DataGrid>
</Grid>
</Grid>
</UserControl>
Here is the code behind using System; using System.Collections.ObjectModel; using System.Reflection; using System.Windows; using System.Windows.Controls;
namespace StackOverflowProblems
{
public partial class MainPage : UserControl
{
ObservableCollection<UserInfo> users = new ObservableCollection<UserInfo>();
ObservableCollection<string> roles = new ObservableCollection<string>();
public MainPage()
{
InitializeComponent();
LayoutRoot.DataContext = this;
InitializeRoles();
}
public void InitializeRoles()
{
// turn enumeration into a collection of strings
Type enumType = typeof(UserRole);
foreach (FieldInfo fieldInfo in enumType.GetFields(BindingFlags.Public | BindingFlags.Static))
{
roles.Add(fieldInfo.Name.ToString());
}
myComboBox.ItemsSource = roles;
myComboBox.SelectedIndex = 0;
}
public void svc_GetAllUsersCompleted()
{
users.Add(new UserInfo("Fred", UserRole.Administrator));
users.Add(new UserInfo("George", UserRole.None));
users.Add(new UserInfo("Mary", UserRole.Reviewer));
dataGrid1.ItemsSource = users;
}
private void dataGrid1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
private void cmbUserRoleTypes_Loaded(object sender, RoutedEventArgs e)
{
ComboBox bx = (ComboBox)sender;
UserInfo ui = (UserInfo)bx.Tag;
bx.ItemsSource = roles;
int userRoleIndex = 0;
switch (ui.Role)
{
case UserRole.None:
userRoleIndex = 0;
break;
case UserRole.Administrator:
userRoleIndex = 1;
break;
case UserRole.Reviewer:
userRoleIndex = 2;
break;
default:
throw new Exception("Invalid Role Detected");
}
bx.SelectedIndex = userRoleIndex;
}
private void btn_Click(object sender, RoutedEventArgs e)
{
svc_GetAllUsersCompleted();
}
}
}
Here is the supporting class file using System; using System.ComponentModel; using System.Globalization; using System.Windows.Data;
namespace StackOverflowProblems
{
public class UserInfo : INotifyPropertyChanged
{
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
private string _User = "";
public string User
{
get { return _User; }
set
{
if (_User != value)
{
_User = value;
NotifyPropertyChanged("User");
}
}
}
private UserRole _Role = UserRole.None;
public UserRole Role
{
get { return _Role; }
set
{
if (_Role != value)
{
_Role = value;
NotifyPropertyChanged("User");
}
}
}
public UserInfo(string user, UserRole role)
{
User = user;
Role = role;
}
}
public enum UserRole
{
None = 0,
Administrator = 1,
Reviewer = 2,
}
}
It is also very possible for your SelectedValue to receive it's value before the ItemsSource gets its value for GetListOfRoles.
If I remember right, that can cause issues with the 'value' being set to an item that does not exist in the ItemsSource yet.
精彩评论