Часто возникает необходимость как-то кастомизировать ряды данных в DataGrid, например выделить цветом ряды, в которых хранятся данные с определенными свойствами.
Можно разделить задачу на две подзадачи:
1. Раскрашиваение грида при его создании.
2. Изменение цвета ряда при его изменении при помощи формы с данными.
По очереди рассмотрим эти задачи:
Интересно то, что получить список рядов в DataGrid в Silverlight 4 нельзя. Иначе наша задача решалась бы очень просто, поскольку этого сделать нельзя будем использовать обходные пути.
Для того чтобы решить первую задачу нам нужно подписаться на событие LoadingRow нашего грида. В обработчике выполнить свой код проверки состояния контекста данных.
Ничего сложного:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Navigation;
using MyApplication.Web.Services;
using MyApplication.BLL;
using System.Threading;
using System.ComponentModel;
using System.ServiceModel.DomainServices.Client;
namespace MyApplication.Views
{
public partial class SomePage : Page
{
public SomePage()
{
if (WebContext.Current.User.IsAuthenticated)
{
InitializeComponent();
someDataGrid.LoadingRow += new EventHandler<DataGridRowEventArgs>(someDataGrid_LoadingRow);
}
}
void someDataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
{
var some = e.Row.DataContext as SomeTable;
if (some.IsNeedToDrawRed)
{
e.Row.Foreground = new SolidColorBrush(Colors.Red);
}
else
{
e.Row.Foreground = new SolidColorBrush(Colors.Black);
}
}
// Executes when the user navigates to this page.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (!WebContext.Current.User.IsAuthenticated)
{
this.NavigationService.Navigate(new Uri("/Home", UriKind.Relative));
return;
} }
private void someDomainDataSource_LoadedData(object sender, LoadedDataEventArgs e)
{
if (e.HasError)
{
System.Windows.MessageBox.Show(e.Error.ToString(), "Load Error", System.Windows.MessageBoxButton.OK);
e.MarkErrorAsHandled();
}
}
private void OpenSomeViewForm()
{
var window = new SomeTableView();
window.CurrentSome = (SomeTable)someDataGrid.SelectedItem;
window.Context = someDomainDataSource.DomainContext;
window.ParentLayoutRoot = LayoutRoot;
window.Show();
window.Closed += new EventHandler(window_Closed);
}
void window_Closed(object sender, EventArgs e)
{
if (someDomainDataSource.HasChanges)
{
someDomainDataSource.DomainContext.SubmitChanges();
if (someDomainDataSource.CanLoad)
{
someDomainDataSource.Clear();
someDomainDataSource.Load();
}
}
}
private void someDataGrid_DoubleClick(object sender, MouseButtonEventArgs e)
{
OpenSomeViewForm();
}
}
}
Решение следующей задачи ялвяется, пожалуй, гораздо менее очевидным. Предположим, что в форме открываемой при двойной нажатии мышью на ряд мы изменили поле IsNeedToDrawRed. Данные в гриде обновятся, но вот цвет ряда не изменится.
Получается, что нам нужно самостоятельно найти измененный ряд (в простом случае – это текущий ряд грида) и изменить его цвет если это нужно.
Сделаем эту проверку при закрытии окна с формой.
Код будет достаточно хитрым: нам нужно будет получить текущий объект данных, из него полуичть ячейку данных, а уже их нее мы сможет получить текущий ряд. (запутано, но иначе не получается)
private void OpenSomeViewForm()
{
var window = new SomeView();
window.CurrentSome = (Some)someDataGrid.SelectedItem;
window.Context = someDomainDataSource.DomainContext;
window.ParentLayoutRoot = LayoutRoot;
window.Show();
window.Closed += new EventHandler(window_Closed);
}
void window_Closed(object sender, EventArgs e)
{
if (someDomainDataSource.HasChanges)
{
someDomainDataSource.DomainContext.SubmitChanges();
if (someDomainDataSource.CanLoad)
{
someDomainDataSource.Clear();
someDomainDataSource.Load();
}
}
SomeTable some = (SomeTable)someDataGrid.SelectedItem;
FrameworkElement feTemp = someDataGrid.Columns[1].GetCellContent(some);
DataGridRow currentRow = DataGridRow.GetRowContainingElement(feTemp);
currentRow.DataContext = null;
currentRow.DataContext = some;
if (some.IsNeedToDrawRed)
{
currentRow.Foreground = new SolidColorBrush(Colors.Red);
}
else
{
currentRow.Foreground = new SolidColorBrush(Colors.Black);
}
}
SomePage.xaml
<navigation:Page x:Class="MyApplication.Views.SomePage"
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"
Style="{StaticResource PageStyle}"
xmlns:riaControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.DomainServices"
xmlns:my="clr-namespace:MyApplication.Web.Services"
xmlns:my1="clr-namespace:MyApplication.BLL"
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
xmlns:my2="clr-namespace:MyApplication.Controls"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:behaviors="clr-namespace:MyApplication.Helpers;assembly=MyApplication"
xmlns:converter="clr-namespace:MyApplication"
>
<navigation:Page.Resources>
<converter:VisibilityConverter x:Key="VisibilityConverter" />
</navigation:Page.Resources>
<Grid x:Name="LayoutRoot">
<ScrollViewer x:Name="PageScrollViewer" Style="{StaticResource PageScrollViewerStyle}" >
<StackPanel x:Name="ContentStackPanel" Style="{StaticResource ContentStackPanelStyle}">
<TextBlock x:Name="HeaderText" Style="{StaticResource HeaderTextStyle}"
Text="{Binding Path=ApplicationStrings.SomesPageTitle, Source={StaticResource ResourceWrapper}}"/>
bility="Collapsed">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Project:" VerticalAlignment="Center"/>
<ComboBox HorizontalAlignment="Left" Height="23" ItemsSource="{Binding ElementName=projectDomainDataSource, Path=Data}" DisplayMemberPath="Name" Name="projectComboBox" Width="120" Margin="10,0,0,0" SelectionChanged="projectComboBox_SelectionChanged">
<ComboBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ComboBox.ItemsPanel>
</ComboBox>
</StackPanel>
<riaControls:DomainDataSource AutoLoad="True" d:DesignData="{d:DesignInstance my1:Some, CreateList=true}" Height="0" LoadedData="someDomainDataSource_LoadedData" Name="someDomainDataSource" QueryName="GetSomeTableQuery" Width="0" >
<riaControls:DomainDataSource.DomainContext>
<my:MyApplicationDomainContext />
</riaControls:DomainDataSource.DomainContext>
<riaControls:DomainDataSource.SortDescriptors>
<riaControls:SortDescriptor PropertyPath="ID" Direction="Ascending"/>
</riaControls:DomainDataSource.SortDescriptors>
<riaControls:DomainDataSource.QueryParameters>
<riaControls:Parameter ParameterName="projectId" Value="{Binding ElementName=projectComboBox, Path=SelectedItem.ID}" />
</riaControls:DomainDataSource.QueryParameters>
</riaControls:DomainDataSource>
<my2:BusyIndicator x:Name="busyIndicator1" IsBusy="{Binding ElementName=someDomainDataSource, Path=DomainContext.IsLoading}" BusyContent="Loading..." >
<sdk:DataGrid AutoGenerateColumns="True" ItemsSource="{Binding ElementName=someDomainDataSource, Path=Data}" Name="someDataGrid" RowDetailsVisibilityMode="VisibleWhenSelected" ColumnWidth="Auto" IsReadOnly="True" SelectionMode="Single" SizeChanged="someDataGrid_SizeChanged">
<i:Interaction.Behaviors>
<behaviors:DataGridDoubleClickBehavior DoubleClick="someDataGrid_DoubleClick"/>
</i:Interaction.Behaviors>
</sdk:DataGrid>
</my2:BusyIndicator>
<sdk:DataPager x:Name="somePager" PageSize="30" Source="{Binding ElementName=someDomainDataSource, Path=Data}">
</sdk:DataPager>
<riaControls:DomainDataSource AutoLoad="True" d:DesignData="{d:DesignInstance my1:Project, CreateList=true}" Height="0" LoadedData="projectDomainDataSource_LoadedData" Name="projectDomainDataSource" QueryName="GetProjectsQuery" Width="0" >
<riaControls:DomainDataSource.DomainContext>
<my:MyApplicationDomainContext />
</riaControls:DomainDataSource.DomainContext>
</riaControls:DomainDataSource>
</StackPanel>
</ScrollViewer>
</Grid>
</navigation:Page>
SomePage.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Navigation;
using MyApplication.Web.Services;
using MyApplication.BLL;
using System.Threading;
using System.ComponentModel;
using System.ServiceModel.DomainServices.Client;
namespace MyApplication.Views
{
public partial class SomePage : Page
{
public SomePage()
{
if (WebContext.Current.User.IsAuthenticated)
{
InitializeComponent();
someDataGrid.LoadingRow += new EventHandler<DataGridRowEventArgs>(someDataGrid_LoadingRow);
}
}
void someDataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
{
var some = e.Row.DataContext as SomeTable;
if (some.IsNeedToDrawRed)
{
e.Row.Foreground = new SolidColorBrush(Colors.Red);
}
else
{
e.Row.Foreground = new SolidColorBrush(Colors.Black);
}
}
// Executes when the user navigates to this page.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (!WebContext.Current.User.IsAuthenticated)
{
this.NavigationService.Navigate(new Uri("/Home", UriKind.Relative));
return;
} }
private void someDomainDataSource_LoadedData(object sender, LoadedDataEventArgs e)
{
if (e.HasError)
{
System.Windows.MessageBox.Show(e.Error.ToString(), "Load Error", System.Windows.MessageBoxButton.OK);
e.MarkErrorAsHandled();
}
}
private void OpenSomeViewForm()
{
var window = new SomeView();
window.CurrentSome = (Some)someDataGrid.SelectedItem;
window.Context = someDomainDataSource.DomainContext;
window.ParentLayoutRoot = LayoutRoot;
window.Show();
window.Closed += new EventHandler(window_Closed);
}
void window_Closed(object sender, EventArgs e)
{
if (someDomainDataSource.HasChanges)
{
someDomainDataSource.DomainContext.SubmitChanges();
if (someDomainDataSource.CanLoad)
{
someDomainDataSource.Clear();
someDomainDataSource.Load();
}
}
SomeTable some = (SomeTable)someDataGrid.SelectedItem;
FrameworkElement feTemp = someDataGrid.Columns[1].GetCellContent(some);
DataGridRow currentRow = DataGridRow.GetRowContainingElement(feTemp);
currentRow.DataContext = null;
currentRow.DataContext = some;
if (some.IsNeedToDrawRed)
{
currentRow.Foreground = new SolidColorBrush(Colors.Red);
}
else
{
currentRow.Foreground = new SolidColorBrush(Colors.Black);
}
}
private void someDataGrid_DoubleClick(object sender, MouseButtonEventArgs e)
{
OpenSomeViewForm();
}
}
}
Комментариев нет:
Отправить комментарий