В Silverlight существует проблема при задании ширины колонок в DataGrid. К сожалению, существует лишь возможность задать ширину колонки в пикселях (еще существуют и другое варианты задания ширины колонки, например, ширина колонки может равняться ширине данных или ширине заголовка колонки, но это также не слишком применимо в реальной жизни), хотя в реальной жизни больше смысла в задании ширины колонки в процентах. Поскольку не свегда заранее известна ширина всего грида в пикселях. Пользователь может работать в произвольном разрешении, а также может растягивать окно с Silverlight приложением до удобных ему размеров.
В этот раз мы реализуем, пожалуй, наиболее распространенных способ задания ширины колонок в процентах.
В теории, для этого существует символ *, например, для того, чтобы задать ширину для некоторой колонки равную 20%, нужно указать Wodth=”0.2*”. Проблема в том, что это не работает.
Предположим, что нам нужно создать три колонки, ширина которых будет состалять 20, 30 и 50 процентов.
Для того, чтобы указать эту ширину мы воспользуемся свойством MinWidth, а дальше, в коде, обработаем это свойство правильным способом. На самом деле можно было использовать любое другое свойство для задания ширины, все равно мы сами переопределим поведение при создании колонок. Свойство MinWidth используетс в силу того, что оно все равно редко когда используется.
Реализуем свой метод растягивания, для этого подпишемся на событие SizeChanged элемента DataGrid.
<sdk:DataGrid AutoGenerateColumns="False" ItemsSource="{Binding ElementName=someDomainDataSource, Path=Data}" Name="someDataGrid" RowDetailsVisibilityMode="VisibleWhenSelected" ColumnWidth="Auto" IsReadOnly="True" SelectionMode="Single" SizeChanged="someDataGrid_SizeChanged">
<sdk:DataGrid.Columns>
<sdk:DataGridTextColumn x:Name="SomeColumn1" Binding="{Binding Path=Some_Data1 }" Header="Some Data1" MinWidth="20"/>
<sdk:DataGridTextColumn x:Name="SomeColumn2" Binding="{Binding Path=Some_Data2 }" Header="Some Data2" MinWidth="30"/>
<sdk:DataGridTextColumn x:Name="SomeColumn3" Binding="{Binding Path=Some_Data3 }" Header="Some Data3" MinWidth="50"/>
</sdk:DataGrid.Columns>
<i:Interaction.Behaviors>
<behaviors:DataGridDoubleClickBehavior DoubleClick="someDataGrid_DoubleClick"/>
</i:Interaction.Behaviors>
</sdk:DataGrid>
В коде обработчика нам нужно получить свойство MinWidth колонки и общую длину грида с данными. По этим параметрам легко определить нужную длину каждой колонки.
private void someDataGrid_SizeChanged(object sender, SizeChangedEventArgs e)
{
DataGrid dg = (DataGrid)sender;
foreach (DataGridColumn dgCol in dg.Columns)
{
dgCol.Width = new DataGridLength((int)(dgCol.MinWidth * dg.ActualWidth / 100));
}
}
Также не стоит забывать о том, что, когда мы устанавливаем значение свойства Width для колонки, событие SizeChanged срабатывает снова. Чтобы не попасть в бесконечный цикл, необходимо добавить следующую проверку:
private void someDataGrid_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (e.PreviousSize.Width == e.NewSize.Width)
{
return;
}
DataGrid dg = (DataGrid)sender;
foreach (DataGridColumn dgCol in dg.Columns)
{
dgCol.Width = new DataGridLength((int)(dgCol.MinWidth * dg.ActualWidth / 100));
}
}
Этот простой код помогает значительно улучшить дизайн приложения, так что, пожалуй, он может пригодиться многим Silverlight прогрммистам.
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();;
}
}
private void someDataGrid_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (e.PreviousSize.Width == e.NewSize.Width)
{
return;
}
DataGrid dg = (DataGrid)sender;
foreach (DataGridColumn dgCol in dg.Columns)
{
dgCol.Width = new DataGridLength((int)(dgCol.MinWidth * dg.ActualWidth / 100));
}
}
// 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 projectDomainDataSource_LoadedData(object sender, LoadedDataEventArgs e)
{
if (e.HasError)
{
System.Windows.MessageBox.Show(e.Error.ToString(), "Load Error", System.Windows.MessageBoxButton.OK);
e.MarkErrorAsHandled();
}
else
{
var list = ((DomainDataSource)sender).Data.OfType<Project>().ToList<Project>();
var allProjects = new Project();
allProjects.Name = "All Projects";
list.Insert(0, allProjects);
projectComboBox.ItemsSource = list;
projectComboBox.SelectedIndex = 0;
}
}
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();
}
}
}
private void someDataGrid_DoubleClick(object sender, MouseButtonEventArgs e)
{
OpenSomeViewForm();
}
}
}
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="False" ItemsSource="{Binding ElementName=someDomainDataSource, Path=Data}" Name="someDataGrid" RowDetailsVisibilityMode="VisibleWhenSelected" ColumnWidth="Auto" IsReadOnly="True" SelectionMode="Single" SizeChanged="someDataGrid_SizeChanged">
<sdk:DataGrid.Columns>
<sdk:DataGridTextColumn x:Name="SomeColumn1" Binding="{Binding Path=Some_Data1 }" Header="Some Data1" MinWidth="20"/>
<sdk:DataGridTextColumn x:Name="SomeColumn2" Binding="{Binding Path=Some_Data2 }" Header="Some Data2" MinWidth="30"/>
<sdk:DataGridTextColumn x:Name="SomeColumn3" Binding="{Binding Path=Some_Data3 }" Header="Some Data3" MinWidth="50"/>
</sdk:DataGrid.Columns>
<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>
Комментариев нет:
Отправить комментарий