我们经常需要一个按钮,在按下时,后台执行Task,这时不能再次按下按钮。

转自:http://blog.csdn.net/51357/article/details/1480599

韦德国际 1

近期在维护一个vs2008开发的项目(该项目是从Vs2013拷贝升级过来的),发现不同时期按时间顺序来说,分别使用了DataGrid和GridView控件,

我们使用自定义控件,首先新建一个类,我把它命名是ProgressButton

下面引用一篇文章来说说二者不同:

一个进度条按钮,也就是我们按下时发生进度条,完成时他又是按钮。

一、GridView和DataGrid的异同

我们需要一个值让我们知道是不是已经完成了后台,按钮可以按下,在按下时,自动让按钮IsEnable为false。

GridView 是 DataGrid的后继控件,在.net framework 2
中,虽然还存在DataGrid,但是GridView已经走上了历史的前台,取代DataGrid的趋势已是势不可挡。GridView和
DataGrid功能相似,都是在web页面中显示数据源中的数据,将数据源中的一行数据,也就是一条记录,显示为在web页面上输出表格中的一行。

我们需要模板有TextBlock,显示文字,ProgressRing显示进度条。

GridView相对于DataGrid来说,具有如下优势,功能上更加丰富,因为提供了智能
标记面板(也就是show smart
tag)更加易用方便,常用的排序、分页、更新、删除等操作可以零代码实现!具有PagerTemplate属性,可以自定义用户导航页面,也就是说分页
的控制更加随心所欲。GridView和DataGrid在事件模型上也多有不同之处,DataGrid控件引发的都是单个事件,而GridView控件
会引发两个事件,一个在操作前发生,一个在操作后发生,操作前的事件多位***ing事件,操作后的事件多位***ed事件,比如Sorting
事件和sorted 事件,RowDeleting和RowDeleted事件。

于是我们使用TemplatePart

 

    [TemplatePart(Name = "TextBlock", Type = typeof(TextBlock))]
    [TemplatePart(Name = "Progress", Type = typeof(Windows.UI.Xaml.Controls.ProgressRing))]
    public class ProgressButton : Windows.UI.Xaml.Controls.Button

二、GridView操作初步

依赖属性其实很简单,我们需要在VS上大propdp 按Tab
就可以看到vs帮我们写的依赖属性。

 

我们需要修改属性名称,属性类型,默认值。

1、显示数据源中的数据

我这里的Text ,需要他修改时使用函数,这个叫CallBack。

从ToolBox中选取GridView控件拖到页面上,然后点击右键,选择Show Smart
Tag,在Choose Data Source中选择 New Data Source, 出现Data Source
Configuration
Wizard,选择连接字符串,可以选择已经存放在web.config中的ConnectionString
,然后可以选择是使用存储过程,还是从表或视图中选择数据。

依赖函数使用DependencyProperty.Register

在这一步,左侧的Where语句可以指定查询条件,点击Where,出现Add Where
Clause
,选择要设定条件的列,操作符是等于还是like还是其它,然后选择Source,也就是说要限定的条件从哪里取值,可以是Control、
Session、Form、Cookie、QueryStirng等,如果选择Control,那么需要在右侧,选中是那个控件,然后还可以设定默认值,
设定完后系统自动生成Sql
表达式和值的表达式,此时点击Add按钮,完成条件的添加,Where
Cluase下出现刚刚添加的条件。如果没有点击Add,很容易设定了条件,但是因为没有添加到Where子句中,所以不起作用。

他参数: name 是 属性名, propertyType 是属性类型, ownerType
是属于的类的类型, typeMetadata 是默认值和修改时使用函数

在这一步,左侧的Order
By,可以让我们设定排序列,就是我们取出的记录要按照什么派逊,可以设定三个列,是升序还是降序。

我们来说下 typeMetadata

在这一部,左侧的Advanced,可以设定Advanced Sql Generation
Options,这里可以生成这个查询的Insert、update、Delete语句,当然,前提是您选择的字段中必须包含了主键。当您想在
GridView中不编写任何代码实现对表格的编辑、删除等操作时,就必须在配置数据源时,在这里生成Insert、Update、Delete这些语
句。
GridView中编辑删除等操作的零代码,就是根据配置数据源时自动生成的这些语句来完成数据源的更新删除等操作的。

typeMetadata
可以传入一个默认值,这个值就是我们不在依赖属性赋值,就给他一个默认的值。然后我们还可以给他一个在属性修改时使用的函数。

在最后一步,您可以测试一下您刚刚生成的查询是否正确,最后点击完成,数据已经出现在页面上了,按Ctrl+F5运行。

注意我们给他的函数不是必需,一般都不需要。

恭喜您!您已经会使用Asp.net来显示数据库中的数据了。

如果需要给他一个函数,这个函数需要有参数DependencyObject sender, DependencyPropertyChangedEventArgs e

 

其中 sender
是发送的实例,我们知道属性属于哪个类,我在这里,是属于ProgressButton
,我就可以使用
ProgressButton button = sender as ProgressButton;得到类,注意我们写的函数是静态的,所以sender才有用,我们可以使用sender获得类的属性

2、让GridView可以分页

e 是有 NewValue 和 OldValue , NewValue 是我们要修改的值, OldValue
是原来的值。

 

大概需要的依赖属性在我们这个控件有 Text Complete 就没了。

GridView把数据显示出来了,但是那么多条记录罗列到一页上是不合适的,我们应该对数据
进行分页。还记得在asp时代,分页是多么的麻烦,需要编写很多的代码,而且各种分页组件也应运而生。而在GridView中,您会发现,分页是如此的简
单,只需要您轻点鼠标,在Show Smart Tag中,选中Enable
Paging,表格的分页操作变完成了,是不是So Easy呢。

Text是我们按钮的文字,Complete
是我们的后台是不是在执行,如果是的话,按钮就无法点击,显示进度条。

并不是什么数据源都可以让GridView实现自动分页的,比如如果
DataSourceMode是DataReader,就无法实现自动分页。而且只有ObjectDataSource是界面级别的支持分页,类似我们常
用的SqlDataSource都是先提取所有的记录,然后只显示本页需要显示的记录,然后抛弃其余的记录,都有点浪费资源的啦!

代码:

当GridView的AllowPaging属性设置为True的时候,我们实现了分页,我们
还可以对分页进行一些个性化的设置。常用的属性包括:PageIndex――设置数据显示的当前页面,默认是0,也就是数据的首页。PageSize
――也就是一页显示多少条记录,默认为10条。在PagerSettings中,还可以对分页的导航按钮进行详细设置,在Mode属性中,可以设置:
Numeric――默认的,分页用数字表示,1,2,3……。NextPrevious、NextPreviousFirstLast、
NumericFirstLast均可顾名思义,显示上一页、下一页、首页、末页等。当Mode设定不是Numeric时,那么可以通过设定
FirstPageText、LastPageText等属性来实现分页导航时,到首页、末页、下页、上页时显示的文字提示。

using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace lindexi.uwp.control.Button.Control
{
    [TemplatePart(Name = "TextBlock", Type = typeof(TextBlock))]
    [TemplatePart(Name = "Progress", Type = typeof(Windows.UI.Xaml.Controls.ProgressRing))]
    public class ProgressButton : Windows.UI.Xaml.Controls.Button
    {
        public ProgressButton()
        {
            DefaultStyleKey = typeof(ProgressButton);
            Click += ProgressButton_Click;
        }

        private void ProgressButton_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
        {
            Complete = false;
        }

        private Windows.UI.Xaml.Controls.TextBlock _textBlock;

        private Windows.UI.Xaml.Controls.ProgressRing _proress;

        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Text.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register("Text", typeof(string), typeof(ProgressButton), new PropertyMetadata("",
                (d, e) =>
                {
                    ProgressButton temp = d as ProgressButton;
                    if (temp == null)
                    {
                        return;
                    }
                    if(temp._textBlock!=null)
                    {
                        temp._textBlock.Text = (string) e.NewValue;
                    }
                }));



        public bool Complete
        {
            get { return (bool)GetValue(CompleteProperty); }
            set { SetValue(CompleteProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Complete.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CompleteProperty =
            DependencyProperty.Register("Complete", typeof(bool), typeof(ProgressButton), new PropertyMetadata(true,
                OnComplete));

        private static void OnComplete(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ProgressButton button = d as ProgressButton;
            if (button == null)
            {
                return;
            }

            bool temp = (bool)e.NewValue;


            //button._textBlock.Visibility = temp ? Visibility.Visible : Visibility.Collapsed;
            button._proress.Visibility = temp ? Visibility.Collapsed : Visibility.Visible;
            button.IsEnabled = temp;
        }



        protected override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            _textBlock = GetTemplateChild("TextBlock") as Windows.UI.Xaml.Controls.TextBlock;
            _proress = GetTemplateChild("Progress") as Windows.UI.Xaml.Controls.ProgressRing;

            if (_textBlock != null)
            {
                _textBlock.Visibility = Visibility.Visible;
                _textBlock.Text = Text;
            }

            if (_proress != null)
            {
                _proress.Visibility=Visibility.Collapsed;
            }
        }
    }
}

如果想实现分页界面的完全自动控制,还可以点击GridView右键,选择编辑模版-
PagerTemplate来实现,在模版中加入若干个Button控件,然后将Button控件的CommandName属性设置为Page,将
CommandArgument属性分别设置为First、Last、Prev、Next或者一个数字,即可实现分页操作。

我们在控件 OnApplyTemplate 拿到 _textBlock _proress
我们需要写一个Style

 

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:control="using:lindexi.uwp.control.Button.Control">
    <Style TargetType="control:ProgressButton">
        <Setter Property="Background" Value="{ThemeResource ButtonBackground}"/>
        <Setter Property="Foreground" Value="{ThemeResource ButtonForeground}"/>
        <Setter Property="BorderBrush" Value="{ThemeResource ButtonBorderBrush}"/>
        <Setter Property="BorderThickness" Value="{ThemeResource ButtonBorderThemeThickness}"/>
        <Setter Property="Padding" Value="8,4,8,4"/>
        <Setter Property="HorizontalAlignment" Value="Left"/>
        <Setter Property="VerticalAlignment" Value="Center"/>
        <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
        <Setter Property="FontWeight" Value="Normal"/>
        <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}"/>
        <Setter Property="UseSystemFocusVisuals" Value="True"/>
        <Setter Property="FocusVisualMargin" Value="-3"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="control:ProgressButton">
                    <Grid x:Name="RootGrid" Background="{TemplateBinding Background}">
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Normal">
                                    <Storyboard>
                                        <PointerUpThemeAnimation Storyboard.TargetName="RootGrid"/>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="PointerOver">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="RootGrid">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBackgroundPointerOver}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="ContentPresenter">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBorderBrushPointerOver}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonForegroundPointerOver}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextBlock" Storyboard.TargetProperty="Foreground">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonForegroundPointerOver}"></DiscreteObjectKeyFrame>
                                        </ObjectAnimationUsingKeyFrames>
                                        <PointerUpThemeAnimation Storyboard.TargetName="RootGrid"/>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Pressed">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="RootGrid">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBackgroundPressed}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="ContentPresenter">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBorderBrushPressed}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonForegroundPressed}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <PointerDownThemeAnimation Storyboard.TargetName="RootGrid"/>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Disabled">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="RootGrid">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBackgroundDisabled}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="ContentPresenter">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBorderBrushDisabled}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonForegroundDisabled}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextBlock" Storyboard.TargetProperty="Foreground">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonForegroundDisabled}"></DiscreteObjectKeyFrame>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <ContentPresenter x:Name="ContentPresenter" 
                                          AutomationProperties.AccessibilityView="Raw" 
                                          BorderBrush="{TemplateBinding BorderBrush}" 
                                          BorderThickness="{TemplateBinding BorderThickness}"
                                          ContentTemplate="{TemplateBinding ContentTemplate}" 
                                          ContentTransitions="{TemplateBinding ContentTransitions}"
                                          Content="{TemplateBinding Content}" 
                                          HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" 
                                          Padding="{TemplateBinding Padding}" 
                                          VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        <TextBlock x:Name="TextBlock" Margin="10,10,10,10"
                                   HorizontalAlignment="Center"
                                   VerticalAlignment="Center"></TextBlock>
                        <ProgressRing x:Name="Progress" IsActive="True"></ProgressRing>

                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

3、GridView中的编辑、删除、排序

这个是从Button复制,就改了Button为 control:ProgressButton

数据从数据源中提取出现,显示在网页上后,我们如果需要对其中的数据进行编辑、更新、删除等操作,还是不需要编写任何代码,利用GridView内置的功能即可实现。

我们要使用按钮,需要在资源写

在智能标记中,点击编辑列,在Avaliable
Fields中,选择ComandField,然后双击Edit,update,cancel和Delete,我们就为GridView添加了编辑和删除
功能。如果在配置数据源的时候,我们已经生成了Insert、update、delete这些语句,那么我们现在就可以执行程序。点击页面上的Edit,
出现Update和Cancel按钮,同时当前行除了主键以外的列,数值都放在了一个文本框中,可以进行编辑,然后点击Update即可保存。点击
Delete,删除当前行记录。您是不是已经被GridView强大的功能折服了呢?

    <Page.Resources>
        <ResourceDictionary Source="Control/ProgressButton.xaml"></ResourceDictionary>
    </Page.Resources>

在Show Smart Tag中,选择Enable
Sorting,这时所有列的Header都变成了一个超链接,其实这些都是一个LinkButton控件,运行代码,在网页生成的数据表中,点击第一行中的列名,即可按照当前列进行排序,再次点击则反向排序。

然后就可以使用 ProgressButton
,我写ProgressButton在control文件夹,我需要在命名空间xmlns:control="using:lindexi.uwp.control.Button.Control"

如果您只需要对其中的几列进行排序,可以在智能标记中,选择编辑列,选中要排序的列,然后在右
侧的属性中找到SortExpression属性,然后从下拉框中选择根据哪个字段排序,一般当然是当前字段咯,完成排序的设置。如果您不需要这一列参与
排序,那么只需要把此列的SortExpression属性后面的值删除,也就是说设置成空字符串即可。试一试,是不是排序已经尽在掌握之中了呢?

 <control:ProgressButton Text="确定"
                                 Complete="{x:Bind View.Complete,Mode=TwoWay}"
                                 Click="ButtonBase_OnClick"></control:ProgressButton>

 

我上面是测试,点击是进行100秒,过了就完成,代码简单,如果想知道,戳此链接
https://github.com/lindexi/UWP/tree/master/uwp/control/Button

三、GridView中的自定义列

那么如果我们有好多个页面都用到 ProgressButton ,我们需要在所有页面都写
ResourceDictionary 这样不好,我们有一个简单方法,让页面不用写这个。

GridView可以根据数据源自动生成列,但是如果我们需要自定义列的显示方式,让
GridView的列完完全全的由我们自己来控制,我们就需要用到一种特殊的列――TemplateField。因为GridView生成的列都是一个字
段一列,如果我们需要把两个字段合并为一列显示呢?我们可以使用模板列。我们可以指定包含标记和控件的模版,自定义列的布局和行为,我们可以新建一个模版
列,也可以直接把已经生成的列转换为模版列来进行个性化的设置。

在解决方案新建一个文件夹Themes,注意命名一定是Themes,注意有个名称后面有个s,我就在这坑好多天了。

在GridView上单击右键,选择编辑模版,在弹出菜单中选择要编辑的列,出现列模版的编辑
画面。其中HeaderTemplate――自定义列的标头部分显示的内容,FooterTemplate――脚注部分显示哪谌荩?/SPAN>
ItemTemplate――是打开网页后此列数据显示的内容,EditItemTemplate――此列处于编辑状态时如何显示,
AlternatingItemTemplate――交替项显示的内容,也就是说为了显示效果,可以隔行分别以不同的风格显示。

然后新建资源字典 Generic.xaml ,注意名称也是不能自己修改。

Example 1:

在 Generic.xaml 合并字典

我们现在假设有一个表,其中有一个字段是username,我们现在产生一个自定义列,自定义
列中包含此人的照片,同时我们假定照片的路径为image/username.jpg。我们首先右键点击GridView,在智能标记中,选择编辑列,添
加一个模版列,然后编辑模版中的ItemTemplate,加入一个Image控件,然后右键点击Image控件,选择Edit
DataBindings,在ImageUrl中设置Field Binding,首先我我要Bound to
数据源中的某列,因为所有图片的路径和格式是相同的,唯有名字不同而已,所以我们这里选中username字段,在format中,我们要自己定义其格
式,输入image/{0}.jpg, {0}代表的就是上面绑定的字段,下面有一个Two Way
DataBinding
的复选框,就是是否双向绑定的意思,如果单向绑定,一般采用Eval,也就是说数值只从数据源传到页面上,如果双向绑定,也就是采用Bind的话,对数据
的修改可以回传到数据源之中。

    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="ms-appx:///Control/ProgressButton.xaml"></ResourceDictionary>
    </ResourceDictionary.MergedDictionaries>

在web页面执行时,不同的行因为username不同,图片的名字也会做出相应的替换。点击确定,然后执行当前网页,我们就可以看到在我们的自定义列中显示出了用户的照片。

这样我们就可以在页面直接用。

Example 2:

如果使用遇到问题,欢迎讨论。

在数据库中,存储性别的时候,一般采用bit数据类型,存储为True或者False,在
GridView自动生成列的时候,一般使用CheckedBoxField
列来显示bit类型的数据,显示在网页上就是一个单选框,如果选中,也就是Checked了,就是男的,否则就是女的。这样看起来,很不直观,下面我们通
过自定义列将性别显示为男、女。

参见:http://www.cnblogs.com/ms-uap/p/5520872.html

首先在GridView的Show Smart Tag中,选择编辑列,然后双击TemplateFields
,添加了一个模版列,确定后,点击右键选择编辑模版,选中刚添加的列。在ItemTemplate中添加一个DropListDown控件,然后编辑它的
数据绑定,Edit DataBinding,把SelectedValue属性绑定到性别列。

韦德国际 2
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0
国际许可协议
进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接:http://blog.csdn.net/lindexi_gd
),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系

在DropListDown控件中选择 Edit
Item,就是编辑其下拉列表的项,我们添加两个Item,一个的Text属性是男,Value设置为True,一个的Text属性设置为女,Value
属性设置为False。到这里,你明白了么?因为DropDownList控件的显示文本和其值是可以不一样的,我们用数据绑定取到了性别这一列的值,
True或者False,然后反映到DropDownList控件上,如果值为True,因为Text属性为男的Item的Value为True,所以我
们现在运行网页,在新添加的列中,显示的不再是单选框或者True、false这些没有含义的东西,而是以下拉列表的方式显示出了当前用户是
男还是女。

 

四、自定义列中的数据更新

假设数据库中有一个”权限”字段,值为0代表未审核用户,为1代表一般用户,为9则代表管理员
用户。根据前面所说的自定义列的办法,通过对DropListDown的绑定,在网页中显示权限为
“管理员”,而不是显示数字9。问题产生了,如果我们调整用户权限的话,比如把一般用户更改为管理员,在编辑模版中的用户权限的下拉列表,如何把它的值返
回给数据源来完成更新操作。

我们在EditItemTemplate中设置的DropListDown控件,必须选中了 Two Way
DataBinding,也就是数据双向帮定,这样才能返回数据。前面我们谈到,在GridView中,事件不是单个的,是两个,一个是发生前,一个是发
生后,因为我们需要在数据更新前把下拉列表的权限值传送出去,所以我们需要对GridView1_RowUpdating
进行编码,编码如下:

protected void GridView1_RowUpdating(object sender,
GridViewUpdateEventArgs e)

{

//当前编辑的是哪行?

        int index = GridView1.EditIndex;

 

//取得当前编辑行的GridViewRow对象

        GridViewRow gvr = GridView1.Rows[index];

 

//在当前行中,寻找DropListDown控件

        DropDownList dp = (DropDownList)gvr.FindControl(“editdrop”);

 

//将DropListDown的值赋给NewValues集合中的权限字段。

        e.NewValues[“rights”] = dp.SelectedValue;

}

 

2、RowDataBound事件

在创建gridView控件时,必须先为GridView的每一行创建一个
GridViewRow对象,创建每一行时,将引发一个RowCreated事件;当行创建完毕,每一行GridViewRow就要绑定数据源中的数据,
当绑定完成后,将引发RowDataBound事件。如果说我们可以利用RowCreated事件来控制每一行绑定的控件,那么我们同样可以利用
RowDataBound事件来控制每一行绑定的数据,也就是让数据如何呈现给大家。

还举同样的例子,在数据表中,存在性别列,上面我们用DropListDown控件的DataBounding来表示出了中文的性别,但是毕竟不太美观,我们现在可以利用Label控件和RowDataBound事件来实现完美的中文性别显示。RowDataBound,

首先,还是把性别列,设置为模板列,并添加一个Label控件,将Label控件绑定到数据源的性别段,然后我们在GridView控件属性的事件列表中双击RowDataBound,生成如下事件:

Example:

    protected void GridView1_RowDataBound(object sender,
GridViewRowEventArgs e)

{

//判断当前行是否是数据行

        if (e.Row.RowType == DataControlRowType.DataRow)

        {  //用FindControl方法找到模板中的Label控件

Label lb1= (Label)e.Row.FindControl(“Label1”);

//因为RowDataBound是发生在数据绑定之后,所以我们可以

//判断Label绑定的数据,如果是True,就更改其text属性为男

                if (lb1.Text== “True”)

                      lb1.Text = “男”;

                else

                      lb1.Text = “female”;

        }

    }

 

3、RowType

RowType可以确定GridView中行的类型,RowType是玫举变量
DataControlRowType中的一个值。RowType可以取值包括
DataRow、Footer、Header、EmptyDataRow、Pager、Separator。很多时候,我们需要判断当前是否是数据行,通
过如下代码来进行判断 :

   if (e.Row.RowType == DataControlRowType.DataRow)

 

4、RowDeleting和RowDeleted事件

RowDeleting发生在删除数据之前,RowDeleted发生在删除数据之后。

使用RowDeleting事件,可以在真正删除前再次确认是否删除,可以通过设置GridViewDeleteEventArgs.Cancel=True来取消删除;也可以用于判断当前数据库记录数,如果只剩一条记录且数据库不能为空则提示并取消删除操作。

使用RowDeleted事件,可以在删除后,通过GridViewDeletedEventArgs的Exception属性判断删除过程中是否产生异常,如无异常,则可以显示类似于”
1 Records deleted” 之类的提示信息。

Example:

    protected void GridView1_RowDeleting(object sender,
GridViewDeleteEventArgs e)

{

//取得当前行号,并取得当前行的GridViewRow对象

        int index=e.RowIndex ;

        GridViewRow gvr=GridView1.Rows[index];

//取得当前行第二个单元格中的文字

        str1 = gvr.Cells[1].Text;

//进行提示

        Message.Text  =”您将删除一个用户,其姓名为”+str1 ;

    }

    protected void GridView1_RowDeleted(object sender,
GridViewDeletedEventArgs e)

{

//如果没有产生异常,则提示成功删除,否则提示删除失败

        if (e.Exception == null)

            Message.Text += “<br>您成功删除了”+str1 ;

        else

            Message.Text += “删除失败,请联系管理员”;

}

5、RowEditing事件

在GridView中的行进入编辑模式之前,引发RowEditing事件,如果您需要在编辑记录前进行某些预处理,可以在这里操作。如果想取消对当前行的编辑,可以把GridViewEditEventArgs
对象的 Cancel 属性设置为 true即可。

Example:

    protected void GridView1_RowEditing(object sender,
GridViewEditEventArgs e)

{

//用NewEidIndex取得当前编辑的行号,然后获取gridviewrow对象

        GridViewRow gvr = GridView1.Rows[e.NewEditIndex];

 

//判断,如果当前编辑行姓名栏为admin用户,则取消对当前行的编辑

        if (gvr.Cells[1].Text ==”admin”)

            e.Cancel = true;

}

 

6、RowUpdating和RowUpdated事件

RowUpdating事件发生在更新数据源之前,RowUpdated发生在更新数据源之后。

我们可以在记录更新前利用RowUpdating做一些预处理工作,比如修改密码时,因为密码在数据库中不是明文存储,进行了hash,所以在更新密码前,应该生成其hash值,再进行更新操作。RowUpdated则可以检验更新是否成功。

Example:

    protected void GridView1_RowUpdating(object sender,
GridViewUpdateEventArgs e)

    {

        GridViewRow gvr = GridView1.Rows[GridView1 .EditIndex  ];

//寻找输入密码的控件

        TextBox tb1 = (TextBox)gvr.FindControl(“tb_password”);

//将此控件中的文本hash后,把password存入NewValues这个字典中

        e.NewValues [“password”] =tb1.Text .GetHashCode().ToString ()
;

 

    }

    protected void GridView1_RowUpdated(object sender,
GridViewUpdatedEventArgs e)

{

//如无异常,则更新成功

        if (e.Exception == null)

            Message.Text += “更新成功!”;

    }

 

7、Keys、OldValues、NewValues集合

Keys字典中一般存放的是数据源中的主键字段的key和value的对应值,如果主键由多个
字段组成,那么Keys为每个键字段添加其字段名称和值。OldValues中存放的是要更新的行的字段名和原始值,每个字段为其中的一项。
NewValues中存放的是要更新的行的字段名和修改后的值,每个字段为其中的一项。注意,主键字段只存放于keys集合中。

这三个集合中的每一项都是DictionaryEntry类型的对象,我们可以用DictionaryEntry.Key来确定一个项的字段名称,用DictionaryEntry.Value来确定某项的值。

在上面的例子中,为了把密码明文加密后再存入数据库,我们利用了NewValues字段,重新设置key为password的项的值。为了保证安全性,我们在更新数据前对NewValues中的所有值进行html编码:

 Example1:

 protected void GridView1_RowUpdating(object sender,
GridViewUpdateEventArgs e)

{

//遍历NewValues,取得其中每一对DictionaryEntry对象

       foreach (DictionaryEntry de in e.NewValues)

 

//de.key就是字段名,如果此处单独更新某字段的话,也可以直接填写字段名,//比如
e.NewValues[“password”]

 

       e.NewValues[de.Key] = Server.HtmlEncode(de.Value.ToString());

    }

 

Example2:

    protected void GridView1_RowUpdating(object sender,
GridViewUpdateEventArgs e)

{

//分别利用Keys、OldValues、NewValues取得主键名、原始数据和更新后数据

        Message .Text  = e.Keys[“username”] + “的email地址从” +
e.OldValues[“email”] + “变更为” + e.NewValues[“email”];

}

相关文章