[Silverlight]山寨方法->扩展方法->Behavior以及一些遗憾

本文介绍了一种改进DataGrid滚轮支持的方法,通过扩展方法和Behavior实现了代码复用,并探讨了不同实现方式的优缺点。

在我前两日的博文让DataGrid支持滚轮的山寨方法中所提到的方法非常Dirty,由于本人较懒且项目中只有一个地方应用了这个滚轮设计所以也未将其封装起来。所以嘛。。想复用就得ctrl+c、ctrl+v(这年头这种做法的确雷人)。

扩展方法

不过天底下有懒人就有勤快人,在那篇文章的回复中,dongdongha[未注册用户]兄弟将此方法提炼了出来以便复用,代码如下:

public static void SetMouseScroll<T>(this DataGrid dataGrid) {
    dataGrid.MouseWheel += (sender, e) => {
        DataGrid dataGrid1 = sender as DataGrid;
        if (dataGrid.ItemsSource == null) 
            return;

        if (!e.Handled) {
            int rowsToMove = e.Delta / 120 * -1;

            if (e.Delta > 0) {
                if (dataGrid1.SelectedIndex + rowsToMove < 0) 
                    return;              
            }
            else {
                if (dataGrid1.SelectedIndex + rowsToMove > dataGrid1.ItemsSource.Cast<T>().ToList().Count - 1) 
                    return;            
            }

            dataGrid1.SelectedIndex = dataGrid1.SelectedIndex + rowsToMove;
            dataGrid1.ScrollIntoView(dataGrid1.SelectedItem, dataGrid1.Columns[0]);
        }
    };
}

(注:这兄弟原文中用的是匿名委托,本着能少写就少写的理念,那部分给小改成Lambda了)

通过扩展方法和使用泛型,使得方法的复用性大大增加

调用方式

dataGrid1.SetMouseScroll<Person>();

的确是很方便~

ok,第一步改造就此结束

Behavior

接下来由于我在原文中提到了Behavior,所以就干脆用Behavior再封装一次,核心代码其实还是上面的。

public class DataGridMouseWheelBehavior<T> : Behavior<DataGrid> {

    public string TypeOfBehavior { get; set; }

    public DataGridMouseWheelBehavior() { }

    protected override void OnAttached() {
        base.OnAttached();
        this.AssociatedObject.Loaded += new RoutedEventHandler(AssociatedObject_Loaded);

    }

    void AssociatedObject_Loaded(object sender, RoutedEventArgs e) {
        DataGrid dg = sender as DataGrid;
        dg.MouseWheel += (s2, e2) => {
            if (!e2.Handled) {
                int rowsToMove = e2.Delta / 120 * -1;

                if (e2.Delta > 0) {
                    if (dg.SelectedIndex + rowsToMove < 0)
                        return;
                }
                else {
                    if (dg.SelectedIndex + rowsToMove > dg.ItemsSource.Cast<T>().ToList().Count - 1)
                        return;
                }

                dg.SelectedIndex = dg.SelectedIndex + rowsToMove;
                dg.ScrollIntoView(dg.SelectedItem, dg.Columns[0]);
            }
        };
    }

    protected override void OnDetaching() {
        base.OnDetaching();
    }
}

调用方式

var mousebehavior = new DataGridMouseWheelBehavior<Person>();
mousebehavior.Attach(dataGrid1);

这个调用方式看起来不如扩展方法

  • 非静态,需要实例化
  • 必须Attach,没有扩展方法那么优雅

但其实Behavior的真正意义在于可以在XAML中应用。也就是说Developer封装过的方法,Designer不用知道它到底是如何实现的,只要清楚它是用来做什么的就可以了。美工可以通过Blend非常方便的使用Behavior,在XMAL的标记方式为

<i:Interaction.Behaviors>
    <local:DataGridMouseWheelBehavior />
</i:Interaction.Behaviors>

看上去的确很爽。但为什么我们在这里要使用代码调用的方式而非XAML标记呢?这的确是个遗憾。

关键就在于:<T>---对,就是泛型。XAML中并不支持泛型的声明(这点在WPF中稍好一些,不过依然很弱)。

如果强制的使用Person那么就丧失了Behavior的灵活性,还不如不封装。

这同时也证明我这个例子并不非常适合封装成Behavior

现在我知道的解决方案也只能是苦等盼望随着.NET4.0而来的XAML2009了。

或许您有更好的方法,何不告诉我呢?

多角色体系 支持管理员、商家、消费者三种角色,权限分级管控: 管理员:负责平台整体配置、用户审核、数据监控等全局操作。 商家:管理店铺信息、发布商品、处理订单、回复评价等。 消费者:浏览商品、加入购物车、下单支付、评价商品等。 实现用户注册(手机号 / 邮箱验证)、登录(支持密码 / 验证码 / 第三方登录)、个人信息管理(头像、收货地址、密码修改)。 权限精细化控制 商家仅能管理自家店铺及商品,消费者仅能查看和购买商品,管理员拥有全平台数据访问权限。 二、商品管理功能 商品信息维护 商家可发布商品:填写名称、分类(如服饰、电子产品)、子类别(如手机、笔记本)、规格(尺寸、颜色、型号)、价格、库存、详情描述(图文)、物流信息(运费、发货地)等。 支持商品上下架、库存调整、信息编辑,系统自动记录商品状态变更日志。 商品分类与搜索 按多级分类展示商品(如 “数码产品→手机→智能手机”),支持自定义分类体系。 提供智能搜索功能:按关键词(名称、品牌)搜索,支持模糊匹配和搜索联想;结合用户浏览历史对搜索结果排序(优先展示高相关度商品)。 商品推荐 基于用户浏览、收藏、购买记录,推荐相似商品(如 “浏览过该商品的用户还买了…”)。 首页展示热门商品(销量 TOP10)、新品上架、限时折扣等推荐列表。 三、订单与交易管理 购物车与下单 消费者可将商品加入购物车,支持修改数量、选择规格、移除商品,系统自动计算总价(含运费、折扣)。 下单流程:确认收货地址→选择支付方式(在线支付、货到付款)→提交订单→系统生成唯一订单号。 订单处理流程 订单状态跟踪:待支付→已支付→商家发货→物流运输→消费者收货→订单完成,各状态变更实时通知用户。 商家端功能:查看新订单提醒、确认发货(填写物流单号)、处理退款申请(需审核理由)。 消费者端功能:查看订单详情、追踪物流、申请退款 / 退货、确认收货。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值