понедельник, 30 августа 2010 г.

Немного об аутентификации в Silverlight 4 - Часть 3

Сейчас мы разработаем страницу, с которой можно будет добавлять поных пользователей, а также изменяться их параметры, такие как имя, логин и пароль.

Сначала создадим новую страницу Users.

У нас будет DataGrid с пользователями. Заодно мы посмотрим, как можно создать Select All чекбокс в заголовке колонки.

Users.xaml

<navigation:Page

x:Class="MyApplication.Users"

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:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"

mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480"

Style="{StaticResource PageStyle}" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" 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:my2="clr-namespace:MyApplication.Controls">

<UserControl.Resources>

<Style x:Key="DataGridColumnHeaderStyle" TargetType="sdk:DataGridColumnHeader">

<Setter Property="Foreground" Value="#FF000000"/>

<Setter Property="HorizontalContentAlignment" Value="Left"/>

<Setter Property="VerticalContentAlignment" Value="Center"/>

<Setter Property="IsTabStop" Value="False"/>

<Setter Property="SeparatorBrush" Value="#FFC9CACA"/>

<Setter Property="Padding" Value="4"/>

<Setter Property="Template">

<Setter.Value>

<ControlTemplate TargetType="sdk:DataGridColumnHeader">

<Grid x:Name="Root">

<Grid.ColumnDefinitions>

<ColumnDefinition/>

<ColumnDefinition Width="Auto"/>

</Grid.ColumnDefinitions>

<VisualStateManager.VisualStateGroups>

<VisualStateGroup x:Name="CommonStates">

<VisualState x:Name="Normal"/>

<VisualState x:Name="MouseOver">

<Storyboard>

<ColorAnimation Duration="0" Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="(Fill).Color" To="#FF448DCA"/>

<ColorAnimation Duration="0" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Fill).(GradientStops)[3].Color" To="#7FFFFFFF"/>

<ColorAnimation Duration="0" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Fill).(GradientStops)[2].Color" To="#CCFFFFFF"/>

<ColorAnimation Duration="0" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Fill).(GradientStops)[1].Color" To="#F2FFFFFF"/>

</Storyboard>

</VisualState>

<VisualState x:Name="Pressed">

<Storyboard>

<ColorAnimation Duration="0" Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="(Fill).Color" To="#FF448DCA"/>

<ColorAnimation Duration="0" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Fill).(GradientStops)[0].Color" To="#D8FFFFFF"/>

<ColorAnimation Duration="0" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Fill).(GradientStops)[1].Color" To="#C6FFFFFF"/>

<ColorAnimation Duration="0" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Fill).(GradientStops)[2].Color" To="#8CFFFFFF"/>

<ColorAnimation Duration="0" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Fill).(GradientStops)[3].Color" To="#3FFFFFFF"/>

</Storyboard>

</VisualState>

</VisualStateGroup>

<VisualStateGroup x:Name="SortStates">

<VisualState x:Name="Unsorted"/>

<VisualState x:Name="SortAscending"/>

<VisualState x:Name="SortDescending"/>

</VisualStateGroup>

</VisualStateManager.VisualStateGroups>

<Rectangle x:Name="BackgroundRectangle" Fill="#FF1F3B53" Stretch="Fill" Grid.ColumnSpan="2"/>

<Rectangle x:Name="BackgroundGradient" Stretch="Fill" Grid.ColumnSpan="2">

<Rectangle.Fill>

<LinearGradientBrush EndPoint=".7,1" StartPoint=".7,0">

<GradientStop Color="#FCFFFFFF" Offset="0.015"/>

<GradientStop Color="#F7FFFFFF" Offset="0.375"/>

<GradientStop Color="#E5FFFFFF" Offset="0.6"/>

<GradientStop Color="#D1FFFFFF" Offset="1"/>

</LinearGradientBrush>

</Rectangle.Fill>

</Rectangle>

<Rectangle x:Name="VerticalSeparator" Fill="{TemplateBinding SeparatorBrush}" VerticalAlignment="Stretch" Width="1" Visibility="{TemplateBinding SeparatorVisibility}" Grid.Column="1"/>

<CheckBox x:Name="chkSelectAll" Click="chk_Click" Margin="2,0,0,0" d:LayoutOverrides="Width, Height" VerticalAlignment="Center" HorizontalAlignment="Center"/>

</Grid>

</ControlTemplate>

</Setter.Value>

</Setter>

</Style>

</UserControl.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.UsersPageTitle, Source={StaticResource ResourceWrapper}}"/>

<StackPanel>

<my2:BusyIndicator IsBusy="{Binding ElementName=userDomainDataSource, Path=IsBusy}">

<sdk:DataGrid AutoGenerateColumns="False" ItemsSource="{Binding ElementName=userDomainDataSource, Path=Data}" Name="userDataGrid" RowDetailsVisibilityMode="VisibleWhenSelected" LoadingRow="userDataGrid_LoadingRow" IsReadOnly="True">

<sdk:DataGrid.Columns>

<sdk:DataGridTemplateColumn Width="80" HeaderStyle="{StaticResource DataGridColumnHeaderStyle}">

<sdk:DataGridTemplateColumn.CellTemplate>

<DataTemplate>

<CheckBox x:Name="chk"

HorizontalAlignment="Center"

HorizontalContentAlignment="Center"

VerticalAlignment="Center"></CheckBox>

</DataTemplate>

</sdk:DataGridTemplateColumn.CellTemplate>

</sdk:DataGridTemplateColumn>

<sdk:DataGridTextColumn x:Name="loginColumn" Binding="{Binding Path=Login}" Header="Login" Width="SizeToHeader" />

<sdk:DataGridTextColumn x:Name="nameColumn" Binding="{Binding Path=Name}" Header="Name" Width="SizeToHeader" />

</sdk:DataGrid.Columns>

</sdk:DataGrid>

</my2:BusyIndicator>

<Button Content="Remove selected" Height="23" Name="btnRemove" Width="120" HorizontalAlignment="Left" Margin="10,10,0,0" Click="btnRemove_Click" />

<my2:CustomDataForm x:Name="userDataForm" Margin="0,10,0,0" CurrentItem="{Binding ElementName=userDataGrid, Path=SelectedItem, Mode=TwoWay}"

CommandButtonsVisibility="All" AutoEdit="False" AutoCommit="True" ItemsSource="{Binding ElementName=userDomainDataSource, Path=Data}" EditEnded="userDataForm_EditEnded"/>

</StackPanel>

<riaControls:DomainDataSource AutoLoad="True" d:DesignData="{d:DesignInstance my1:User, CreateList=true}" Height="0" LoadedData="userDomainDataSource_LoadedData" Name="userDomainDataSource" QueryName="GetUsersQuery" Width="0" >

<riaControls:DomainDataSource.DomainContext>

<my:MyApplicationDomainContext />

</riaControls:DomainDataSource.DomainContext>

</riaControls:DomainDataSource>

</StackPanel>

</ScrollViewer>

</Grid>

</navigation:Page>

Чтобы чекбокс в заголовке работал нужно создать коллекцию чекбоксов и обновлять их состояние при нажатии на чекбокс.

private List<CheckBox> _checkboxes;

private void chk_Click(object sender, System.Windows.RoutedEventArgs e)

{

CheckBox chk = sender as CheckBox;

bool check = chk.IsChecked.Value;

foreach (CheckBox chkbox in _checkboxes)

{

chkbox.IsChecked = check;

}

}

private void userDataGrid_LoadingRow(object sender, DataGridRowEventArgs e)

{

CheckBox chk = userDataGrid.Columns[0].GetCellContent(e.Row) as CheckBox;

chk.IsChecked = false;

if (!_checkboxes.Contains(chk))

{

_checkboxes.Add(chk);

}

}

Другого способа сделать это, похоже, пока нет.

При нажатии на кнопку нужно удалять все записи из таблицы, разумеется, после подтверждения пользователя.

private void btnRemove_Click(object sender, System.Windows.RoutedEventArgs e)

{

if (HtmlPage.Window.Confirm("Are you sure you want to remove selected users?"))

{

var ctx = (userDomainDataSource.DomainContext as MyApplicationDomainContext);

foreach (var item in _checkboxes)

{

if (item.IsChecked == true)

{

var row = DataGridRow.GetRowContainingElement(item);

var data = row.DataContext;

ctx.Users.Remove(data as User);

}

}

ctx.SubmitChanges();

}

}

Страница будет доступна только для администраторов, так что в методе OnNavigateTo проверим, является ли пользователь администратором.

protected override void OnNavigatedTo(NavigationEventArgs e)

{

if (!WebContext.Current.User.IsAuthenticated)

{

this.NavigationService.Navigate(new Uri("/Home", UriKind.Relative));

return;

}

if (!WebContext.Current.User.IsAdmin)

{

NavigationService.Navigate(new Uri("/Home", UriKind.Relative));

}

_checkboxes = new List<CheckBox>();

}

Весь код Users.xaml.cs:

namespace MyApplication

{

using System.Windows.Controls;

using System.Windows.Navigation;

using System;

using System.Collections.Generic;

using System.Windows.Browser;

using MyApplication.Web.Services;

using MyApplication.BLL;

/// <summary>

/// <see cref="Page"/> class to present information about the current application.

/// </summary>

public partial class Users : Page

{

private List<CheckBox> _checkboxes;

/// <summary>

/// Creates a new instance of the <see cref="Users"/> class.

/// </summary>

public Users()

{

if (WebContext.Current.User.IsAuthenticated)

{

InitializeComponent();

}

this.Title = ApplicationStrings.UsersPageTitle;

}

/// <summary>

/// Executes when the user navigates to this page.

/// </summary>

protected override void OnNavigatedTo(NavigationEventArgs e)

{

if (!WebContext.Current.User.IsAuthenticated)

{

this.NavigationService.Navigate(new Uri("/Home", UriKind.Relative));

return;

}

if (!WebContext.Current.User.IsAdmin)

{

NavigationService.Navigate(new Uri("/Home", UriKind.Relative));

}

_checkboxes = new List<CheckBox>();

}

protected override void OnNavigatedFrom(NavigationEventArgs e)

{

base.OnNavigatedFrom(e);

}

private void userDomainDataSource_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 chk_Click(object sender, System.Windows.RoutedEventArgs e)

{

CheckBox chk = sender as CheckBox;

bool check = chk.IsChecked.Value;

foreach (CheckBox chkbox in _checkboxes)

{

chkbox.IsChecked = check;

}

}

private void userDataGrid_LoadingRow(object sender, DataGridRowEventArgs e)

{

CheckBox chk = userDataGrid.Columns[0].GetCellContent(e.Row) as CheckBox;

chk.IsChecked = false;

if (!_checkboxes.Contains(chk))

{

_checkboxes.Add(chk);

}

}

private void userDataForm_EditEnded(object sender, DataFormEditEndedEventArgs e)

{

userDomainDataSource.DomainContext.SubmitChanges();

}

private void btnRemove_Click(object sender, System.Windows.RoutedEventArgs e)

{

if (HtmlPage.Window.Confirm("Are you sure you want to remove selected users?"))

{

var ctx = (userDomainDataSource.DomainContext as MyApplicationDomainContext);

foreach (var item in _checkboxes)

{

if (item.IsChecked == true)

{

var row = DataGridRow.GetRowContainingElement(item);

var data = row.DataContext;

ctx.Users.Remove(data as User);

}

}

ctx.SubmitChanges();

}

}

}

}

Теперь нужно разобраться с DataForm, но об этом в следующий раз

Комментариев нет:

Отправить комментарий