Silverlight DataGrid with Comboboxes - selected item not displayed
I am having a problem using comboboxes inside a Silverlight datagrid, both of which are bound to DataContext, which in turn uses RIA to retrieve the data from a database.
The problem I have is when you select a value in the combobox and click off the cell, rather than the cell displaying the newly selected value, the cell shows as empty. However - this only occurs if you select a value which has not already been selected in another cell of the datagrid! Selecting a unique value causes the box to show empty
My code is as follows:
<navigation:Page x:Class="Chemical_Management_System.EditPermissions"
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"
mc:Ignorable="d"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
d:DesignWidth="640" d:DesignHeight="480"
Title="EditPermissions Page" Width="640" HorizontalAlignment="Center"
xmlns:riaControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.DomainServices"
xmlns:my="clr-namespace:Chemical_Management_System.Web"
xmlns:myn="clr-namespace:Chemical_Management_System"
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">
<Grid x:Name="LayoutRoot">
<Border BorderBrush="Silver" BorderThickness="1" Height="45" HorizontalAlignment="Left" Margin="10,10,0,0" Name="Border1" Style="{StaticResource HeaderBackground}" VerticalAlignment="Top" Width="618">
<TextBlock Height="23" Name="TextBlock21" Style="{StaticResource HeaderText}" Text="Edit Permissions" />
</Border>
<riaControls:DomainDataSource AutoLoad="True" d:DesignData="{d:DesignInstance my:Permissions, CreateList=true}" Height="0" Name="PermissionsDomainDataSource" QueryName="GetPermissionsQuery" SubmittedChanges="OnSubmitChanges" Width="0">
<riaControls:DomainDataSource.DomainContext>
<my:DataContext />
</riaControls:DomainDataSource.DomainContext>
</riaControls:DomainDataSource>
<riaControls:DomainDataSource AutoLoad="True" d:DesignData="{d:DesignInstance my:PermissionLookups, CreateList=true}" Height="0" Name="PermissionLookupsDomainDataSource" QueryName="GetPermissionLookupsQuery" Width="0">
<riaControls:DomainDataSource.DomainContext>
<my:DataContext />
</riaControls:DomainDataSource.DomainContext>
</riaControls:DomainDataSource>
<riaControls:DomainDataSource AutoLoad="True" d:DesignData="{d:DesignInstance my:Users, CreateList=true}" Height="0" Name="UsersDomainDataSource" QueryName="GetUsersQuery" Width="0">
<riaControls:DomainDataSource.DomainContext>
<my:DataContext />
</riaControls:DomainDataSource.DomainContext>
</riaControls:DomainDataSource>
<Button Content="Apply" Height="23" HorizontalAlignment="Left" Margin="553,445,0,0" Name="btnApply" VerticalAlignment="Top" Width="75" />
<sdk:DataGrid AutoGenerateColumns="False" Height="378" HorizontalAlignment="Left" ItemsSource="{Binding ElementName=PermissionsDomainDataSource, Path=Data}" Margin="12,61,0,0" Name="PermissionsDataGrid" RowDetailsVisibilityMode="VisibleWhenSelected" VerticalAlignment="Top" Width="615">
<sdk:DataGrid.Columns>
<sdk:DataGridTemplateColumn Header="User" MinWidth="190">
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding User.Name}" Padding="5,0,0,0" />
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
<sdk:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding UsersDomainDataSource}"
Loaded="ComboBoxUsers_Loaded"
SelectionChanged="UsersComboBox_SelectionChanged"
>
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellEditingTemplate>
</sdk:DataGridTemplateColumn>
<sdk:DataGridTemplateColumn Header="Permission" MinWidth="175">
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding PermissionLookup.Description}" />
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
<sdk:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding PermissionLookupsDomainDataSource}"
Loaded="ComboBox_Loaded"
SelectionChanged="PermissionLookupComboBox_SelectionChanged"
>
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Description}" />
</DataTemplate>
开发者_开发技巧 </ComboBox.ItemTemplate>
</ComboBox>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellEditingTemplate>
</sdk:DataGridTemplateColumn>
<sdk:DataGridTextColumn x:Name="DescriptionColumn" Binding="{Binding Path=Description}" Header="Description" MinWidth="245" />
</sdk:DataGrid.Columns>
</sdk:DataGrid>
<Button Content="New" Height="23" HorizontalAlignment="Left" Margin="12,445,0,0" Name="btnNew" VerticalAlignment="Top" Width="75" />
<Button Content="Delete" Height="23" HorizontalAlignment="Left" Margin="93,445,0,0" Name="btnDelete" VerticalAlignment="Top" Width="75" />
<Button Content="Cancel" Height="23" HorizontalAlignment="Left" Margin="472,445,0,0" Name="btnCancel" VerticalAlignment="Top" Width="75" />
</Grid>
Partial Public Class EditPermissions
Inherits Page
Dim Context As New Web.DataContext()
Dim user As New CurrentUser()
Public Sub New()
InitializeComponent()
AddHandler user.userLoadedCompleted, AddressOf userLoaded
End Sub
'Executes when the user navigates to this page.
Protected Overrides Sub OnNavigatedTo(ByVal e As System.Windows.Navigation.NavigationEventArgs)
End Sub
Private Sub userLoaded()
If user.permissionCheck("Admin") = False Then
MessageBox.Show("You do not have permission to access this page")
NavigationService.Navigate(New Uri("/Home", UriKind.Relative))
End If
End Sub
Private Sub PermissionsDomainDataSource_LoadedData(ByVal sender As System.Object, ByVal e As System.Windows.Controls.LoadedDataEventArgs) Handles PermissionsDomainDataSource.LoadedData
If e.HasError Then
System.Windows.MessageBox.Show(e.Error.ToString, "Load Error", System.Windows.MessageBoxButton.OK)
e.MarkErrorAsHandled()
End If
End Sub
Private Sub PermissionLookupsDomainDataSource_LoadedData(ByVal sender As System.Object, ByVal e As System.Windows.Controls.LoadedDataEventArgs) Handles PermissionLookupsDomainDataSource.LoadedData
If e.HasError Then
System.Windows.MessageBox.Show(e.Error.ToString, "Load Error", System.Windows.MessageBoxButton.OK)
e.MarkErrorAsHandled()
End If
End Sub
Private Sub ComboBox_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
' set combobox items source from wherever you want
Dim combo As ComboBox = sender
combo.ItemsSource = Me.PermissionLookupsDomainDataSource.DataView
End Sub
Private Sub ComboBoxUsers_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
' set combobox items source from wherever you want
Dim combo As ComboBox = sender
combo.ItemsSource = Me.UsersDomainDataSource.DataView
End Sub
Private Sub btnApply_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles btnApply.Click
Me.PermissionsDomainDataSource.SubmitChanges()
NavigationService.Navigate(New Uri("/AdminHome", UriKind.Relative))
End Sub
Private Sub btnDelete_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles btnDelete.Click
If PermissionsDataGrid.SelectedItem IsNot Nothing Then
Dim selected As Web.Permissions = PermissionsDataGrid.SelectedItem
Me.PermissionsDomainDataSource.DataView.Remove(selected)
Else
MessageBox.Show("Please select a permission entry to delete")
End If
End Sub
Private Sub btnNew_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles btnNew.Click
Dim permission As New Web.Permissions
Me.PermissionsDomainDataSource.DataView.Add(permission)
End Sub
Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles btnCancel.Click
Me.PermissionsDomainDataSource.RejectChanges()
NavigationService.Navigate(New Uri("/AdminHome", UriKind.Relative))
End Sub
Private Sub OnSubmitChanges(ByVal sender As Object, ByVal e As SubmittedChangesEventArgs)
If (e.HasError) Then
MessageBox.Show("Error: " + e.Error.ToString)
End If
End Sub
Private Sub UsersComboBox_SelectionChanged(ByVal sender As System.Object, ByVal e As System.Windows.Controls.SelectionChangedEventArgs)
Dim permission As Web.Permissions = PermissionsDataGrid.SelectedItem
Dim selected As ComboBox = sender
Dim user As Web.Users = selected.SelectedItem
permission.UserID = user.ID
selected.UpdateLayout()
End Sub
Private Sub PermissionLookupComboBox_SelectionChanged(ByVal sender As System.Object, ByVal e As System.Windows.Controls.SelectionChangedEventArgs)
Dim permission As Web.Permissions = PermissionsDataGrid.SelectedItem
Dim selected As ComboBox = sender
Dim permissionLookup As Web.PermissionLookups = selected.SelectedItem
permission.PermissionID = permissionLookup.ID
End Sub
End Class
Here is the one of the possible solutions..
http://richardgavel.wordpress.com/2009/04/17/silverlight-combobox-and-asynchronous-population-of-underlying-data/
you know, i've sat with this problem for ages, and couldnt find a solution. The second I post it online... it dawns on me. I hate it when that happens. Anyway, the solution is as follows.
Because the database and therefore data objects are constructed with strongly typed links, you can access the user referenced in any given permission group by doing Permission.User.Property. You can also assign to this Permission.User to set the links too.
While I did try to do this previously using DataDomainSources, it always gave me an error, stating the object was already bound to another DataDomainSources. this is because you have one DataDomainSources for Permissions, and one for Users.
This limitation does not exist when using a DataContext however, as both Users and Permissions exist in the same DataContext.
I therefore re-wrote the code as follows:
<navigation:Page x:Class="Chemical_Management_System.EditPermissions"
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"
mc:Ignorable="d"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
d:DesignWidth="640" d:DesignHeight="480"
Title="EditPermissions Page" Width="640" HorizontalAlignment="Center"
xmlns:riaControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.DomainServices"
xmlns:my="clr-namespace:Chemical_Management_System.Web"
xmlns:myn="clr-namespace:Chemical_Management_System"
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">
<Grid x:Name="LayoutRoot" >
<Border BorderBrush="Silver" BorderThickness="1" Height="45" HorizontalAlignment="Left" Margin="10,10,0,0" Name="Border1" Style="{StaticResource HeaderBackground}" VerticalAlignment="Top" Width="618">
<TextBlock Height="23" Name="TextBlock21" Style="{StaticResource HeaderText}" Text="Edit Permissions" />
</Border>
<Button Content="Apply" Height="23" HorizontalAlignment="Left" Margin="553,445,0,0" Name="btnApply" VerticalAlignment="Top" Width="75" />
<Button Content="New" Height="23" HorizontalAlignment="Left" Margin="12,445,0,0" Name="btnNew" VerticalAlignment="Top" Width="75" />
<Button Content="Delete" Height="23" HorizontalAlignment="Left" Margin="93,445,0,0" Name="btnDelete" VerticalAlignment="Top" Width="75" />
<Button Content="Cancel" Height="23" HorizontalAlignment="Left" Margin="472,445,0,0" Name="btnCancel" VerticalAlignment="Top" Width="75" />
<sdk:DataGrid AutoGenerateColumns="False" Height="364" HorizontalAlignment="Left" Margin="10,75,0,0" Name="dataGrid" VerticalAlignment="Top" Width="618" DataContext="dataContext.Permissions">
<sdk:DataGrid.Columns>
<sdk:DataGridTextColumn x:Name="DescriptionColumn" Binding="{Binding Path=Description}" Header="Description" MinWidth="245" />
<sdk:DataGridTemplateColumn Header="User" MinWidth="190">
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding User.Name}" Padding="5,0,0,0" />
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
<sdk:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox Loaded="UserComboBox_Loaded" SelectionChanged="UserComboBox_SelectionChanged">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellEditingTemplate>
</sdk:DataGridTemplateColumn>
<sdk:DataGridTemplateColumn Header="Permission" MinWidth="190">
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding PermissionLookup.Description}" Padding="5,0,0,0" />
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
<sdk:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox Loaded="PermissionComboBox_Loaded" SelectionChanged="PermissionComboBox_SelectionChanged">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Description}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellEditingTemplate>
</sdk:DataGridTemplateColumn>
</sdk:DataGrid.Columns>
</sdk:DataGrid>
</Grid>
Partial Public Class EditPermissions
Inherits Page
Dim Context As New Web.DataContext()
Dim user As New CurrentUser()
Public Sub New()
InitializeComponent()
AddHandler user.userLoadedCompleted, AddressOf userLoaded
Context.Load(Context.GetPermissionsQuery())
Context.Load(Context.GetUsersQuery())
Context.Load(Context.GetPermissionLookupsQuery)
dataGrid.ItemsSource = Context.Permissions
End Sub
'Executes when the user navigates to this page.
Protected Overrides Sub OnNavigatedTo(ByVal e As System.Windows.Navigation.NavigationEventArgs)
End Sub
Private Sub userLoaded()
If user.permissionCheck("Admin") = False Then
MessageBox.Show("You do not have permission to access this page")
NavigationService.Navigate(New Uri("/Home", UriKind.Relative))
End If
End Sub
Private Sub UserComboBox_Loaded(sender As System.Object, e As System.Windows.RoutedEventArgs)
Dim combo As ComboBox = sender
combo.ItemsSource = Context.Users
End Sub
Private Sub UserComboBox_SelectionChanged(sender As System.Object, e As System.Windows.Controls.SelectionChangedEventArgs)
Dim combo As ComboBox = sender
Dim user As Web.Users = combo.SelectedItem
Dim currentPermission As Web.Permissions = dataGrid.SelectedItem
currentPermission.User = user
End Sub
Private Sub PermissionComboBox_Loaded(sender As System.Object, e As System.Windows.RoutedEventArgs)
Dim combo As ComboBox = sender
combo.ItemsSource = Context.PermissionLookups
End Sub
Private Sub PermissionComboBox_SelectionChanged(sender As System.Object, e As System.Windows.Controls.SelectionChangedEventArgs)
Dim combo As ComboBox = sender
Dim permissionLookup As Web.PermissionLookups = combo.SelectedItem
Dim currentPermission As Web.Permissions = dataGrid.SelectedItem
currentPermission.PermissionLookup = permissionLookup
End Sub
Private Sub btnApply_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles btnApply.Click
Context.SubmitChanges()
End Sub
Private Sub btnNew_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles btnNew.Click
Dim newpermission As New Web.Permissions
Context.Permissions.Add(newpermission)
End Sub
End Class
精彩评论