如何在GridView中实现多选

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在GridView中实现多选相关的知识,希望对你有一定的参考价值。

GridView实现跨页多选,参考如下:

JS 前台:

//GridView中实现多选效果
function CheckAllC(oCheckbox) 
    var GridView1 = document.getElementById(\'gvDataList\');
    for (i = 1; i < gvDataList.rows.length; i++) 
        GridView1.rows[i].cells[0].getElementsByTagName("INPUT")[0].checked = oCheckbox.checked;
    

 

后台:

1:GridView翻页PageIndexChanging事件中调用获取多选主键信息,还需要判断一下,翻页之前是否已经有数据选中。具体方法如下:

方法如下:

#region 存储GridView翻页数据主键
        /// <summary>
        /// 存储GridView翻页数据主键
        /// </summary>
        private void RememberOldValues()
       
            Dictionary<string, string> list = Session["SelectedObject"] as Dictionary<string, string>;
            if (list == null)
           
                list = new Dictionary<string, string>();
           
            foreach (GridViewRow row in gvDataList.Rows)
           
                CheckBox cb = (CheckBox)row.FindControl("chkSelect");
                string user = gvDataList.DataKeys[row.RowIndex].Value.ToString();
                if (Session["SelectedObject"] != null)
                    list = (Dictionary<string, string>)Session["SelectedObject"]; //很重要
                if (cb.Checked)
               
                    if (!list.ContainsKey(user))
                   
                        list.Add(user, "null");
                   
               
                else
               
                    if (list.ContainsKey(user))
                   
                        list.Remove(user);
                   
               
                if (list != null && list.Count > 0)
                    Session["SelectedObject"] = list;
           


       
        #endregion

 

附带GridView自带分页:

#region  分页
        protected void gvDataList_PageIndexChanging(object sender, GridViewPageEventArgs e)
       
            RememberOldValues();
            // 得到该控件
            GridView theGrid = sender as GridView;
            int newPageIndex = 0;
            if (e.NewPageIndex == -3)
           
                //点击了Go按钮
                TextBox txtNewPageIndex = null;

                //GridView较DataGrid提供了更多的API,获取分页块可以使用BottomPagerRow 或者TopPagerRow,当然还增加了HeaderRow和FooterRow
                GridViewRow pagerRow = theGrid.BottomPagerRow;

                if (pagerRow != null)
               
                    //得到text控件
                    txtNewPageIndex = pagerRow.FindControl("txtNewPageIndex") as TextBox;
               
                if (txtNewPageIndex != null)
               
                    //得到索引
                    newPageIndex = int.Parse(txtNewPageIndex.Text) - 1;
               
           
            else
           
                //点击了其他的按钮
                newPageIndex = e.NewPageIndex;
           
            //防止新索引溢出
            newPageIndex = newPageIndex < 0 ? 0 : newPageIndex;
            newPageIndex = newPageIndex >= theGrid.PageCount ? theGrid.PageCount - 1 : newPageIndex;

            //得到新的值
            theGrid.PageIndex = newPageIndex;

            //重新绑定
            BindItems(0, NodeID, strSearch);
       
        #endregion

 

2:点击提交按钮时,需要获取下GridView中的多选主键ID

#region 获取单选按钮选中的主键ID
        /// <summary>
        /// 获取单选按钮选中的主键ID
        /// </summary>
        /// <returns></returns>
        private void GetPkID()
       
            Dictionary<string, string> list = Session["SelectedObject"] as Dictionary<string, string>;
            if (list == null)
           
                list = new Dictionary<string, string>();
           
            foreach (GridViewRow row in gvDataList.Rows)
           
                CheckBox cb = (CheckBox)row.FindControl("chkSelect");
                string user = gvDataList.DataKeys[row.RowIndex].Value.ToString();
                if (cb.Checked)
               
                    if (!list.ContainsKey(user))
                   
                        list.Add(user, "null");
                   
               
                else
               
                    if (list.ContainsKey(user))
                   
                        list.Remove(user);
                   
               
           
            ViewState["SelectedObject"] = list;    
       
        #endregion

参考技术A 1 问题:
GridView中图片的展示是没有问题的,但是 当选中了一张or几张图片后,(当展示的图片比较多得情况下,就得滑动gridview已浏览其他的图片),一旦滑动gridview,之前选择的照片就会出现混乱(照片的展示顺序是对的,但是改变的背景会出现在某个没有被选定的照片上面)。
2 我选择照片的方式是:
当用户点击某个照片时,在setOnItemClickListener或者自定适配器的getView中将视图的背景换掉,或者将一个gridview上得cell视图中某个一开始被隐藏的图片设为visible。
但是上面的两种方式会出现“问题”中出现的那种问题。
查了很多材料,一开始是以为使用了ViewHolder的原因,于是每次都去
convertView = inflater.inflate(resource, null); // 生成条目界面对象
cellImageView = (ImageView) convertView.findViewById(R.id.camera_gridview_cell);
结果出了内存溢出的情况。
后来直接将动态去生成一个imageview作为grid view的cell,结果问题依旧,活动后选定的照片会出现混乱。
3 问题的由来:
因为listview和gridview都是使用adapter以MVC的形式来加载数据到视图,而处于某种原因,listview和gridview中第一次展示在屏幕上得cells是新建的,当加载的cells过多时,出现多屏幕时,从第二屏开始复用第一屏中的cells视图,而且貌似复用的顺序也是不确定的,于是就出现了不滑动gridview效果正常,一旦滑动了,效果就会混乱。
4 可能的解决方案:
1 http://www.coderzheaven.com/2013/04/26/multiple-selection-listview-android/ 但是链接中的代码没有工作。
2 http://blog.csdn.net/creativemobile/article/details/9007555 这个可以正常工作
其实每次滑动,活动所有展示在屏幕上得cells都会执行是配置器中的getView方法,在结合“3 问题的由来”的解释,发现,何不将只有在setOnItemClickListener中改变背景的操作,放在getView中,而且不加点击监听器,让他只要执行到getView就去改变背景,只是,只有那些isChecked设为TRUE的才变为我们想要的背景,而其他的改为另一个背景,(注意不能为空,即使isChecked为false)
OK 问题解决了
5 未验证的解决方案:
监听gridview滑动,在onScrollStateChanged方法中获得所有展示在屏幕的cells,将其背景全部更新,发现与上面的解决方案本质上同出一辙。

如何在 Sonata Media Bundle 中实现多对多关系

【中文标题】如何在 Sonata Media Bundle 中实现多对多关系【英文标题】:How to implement many-to-many relationships in Sonata Media Bundle 【发布时间】:2012-07-21 17:08:54 【问题描述】:

我正在尝试将 SonataMediaBundle 与另一个实体相关联:Products 与 ManyToMany 关系。

架构和关系创建良好。

但是,当我编辑或创建新产品时,我尝试添加一个按钮,我可以在其中通过媒体库搜索媒体文件,并添加一个按钮来上传新文件。

对于 OneToMany 关系,这很容易在 Admin\ProductAdmin::configureFormFields 中通过添加:

->add('image', 'sonata_type_model_list', array(
                    'required' => false
                ), array(
                    'link_parameters' => array(
                        'context'  => 'default',
                        'provider' => 'sonata.media.provider.image'
                     )
                ))

所以我得到了与 SonataMediaBundle 库中已使用的相同的 3 个图标(从库中添加上传删除

但是 在多对多关系上,这是不可能的!因为每次我选择一种媒体时,它都会取代之前的媒体。所以我不能选择多种媒体类型。

我想过使用与 The Gallery 相同的方式 (galleryHasMedia)

->add('galleryHasMedias', 'sonata_type_collection', array(
            'by_reference' => false
        ), array(
            'edit'     => 'inline',
            'inline'   => 'table',
            'sortable' => 'position',
            'link_parameters' => array('context' => $context)
        ))

但是,它确实很复杂。 如何通过多对多关系在另一个实体上选择或上传多个媒体文件?

【问题讨论】:

-&gt;add('image', 'sonata_type_model', array('required' =&gt; false, 'multiple'=&gt;true)) 呢? 您可以找到示例演示@sonata-media-upload-multiple-images 【参考方案1】:

您需要依赖 MediaBundle Gallery。在您的实体中,您类似于:

/**
 * @ORM\ManyToOne(targetEntity="Application\Sonata\MediaBundle\Entity\Gallery")
 * @ORM\JoinColumn(name="image", referencedColumnName="id")
 */
private $images;

然后在您的表单中,您将能够使用以下内容将图库链接到您的对象:

->add('images', 'sonata_type_model_list', array('required' => false), array('link_parameters' => array('context' => $context)))

【讨论】:

【参考方案2】:

我和你有同样的问题,但我已经解决了。

首先,您可能希望选择一对多/多对一关系(使用中间实体)而不是多对多关系。为什么?因为这允许额外的列,例如position 列。这样,您可以以任何您想要的方式重新排序图像。在多对多关系中,链接表只有两列:关联表的 id。

来自Doctrine documentation:

(...) 您经常希望将附加属性与关联关联,在这种情况下您需要引入关联类。因此,直接的多对多关联消失了,取而代之的是三个参与类之间的一对多/多对一关联。

所以我将此添加到我的产品映射文件中:(如您所见,我使用 YAML 作为我的配置文件格式)

oneToMany:
    images:
        targetEntity: MyBundle\Entity\ProductImage
        mappedBy: product
        orderBy:
            position: ASC

我创建了一个新的 ProductImage 映射文件:

MyBundle\Entity\ProductImage:
    type: entity
    table: product_images
    id:
        id:
            type: integer
            generator:  strategy: AUTO 
    fields:
        position:
            type: integer
    manyToOne:
        product:
            targetEntity: MyBundle\Entity\Product
            inversedBy: images
        image:
            targetEntity: Application\Sonata\MediaBundle\Entity\Media

使用命令行 (php app/console doctrine:generate:entities MyBundle) 我创建/更新了相应的实体(ProductProductImage)。

接下来,我创建/更新了管理类。 ProductAdmin.php:

class ProductAdmin extends Admin

    protected function configureFormFields(FormMapper $formMapper)
    
        $formMapper
            // define other form fields
            ->add('images', 'sonata_type_collection', array(
                'required' => false
            ), array(
                'edit' => 'inline',
                'inline' => 'table',
                'sortable'  => 'position',
            ))
        ;
    

ProductImageAdmin.php:

class ProductImageAdmin extends Admin

    protected function configureFormFields(FormMapper $formMapper)
    
        $formMapper
            ->add('image', 'sonata_type_model_list', array(
                'required' => false
            ), array(
                'link_parameters' => array(
                    'context' => 'product_image'
                )
            ))
            ->add('position', 'hidden')
        ;
    

不要忘记将它们都添加为服务。如果您不想在仪表板上显示 ProductImage 表单的链接,请添加 show_in_dashboard: false 标记。 (具体怎么做取决于你使用的配置格式(yaml/xml/php))

在此之后,我的管理表单正常工作,但我在尝试保存产品时仍然遇到了一些问题。为了解决所有问题,我必须执行以下步骤:

首先,我必须为 Product 实体配置级联持久化操作。同样,如何执行此操作取决于您的配置格式。我使用的是yaml,所以在images一对多的关系中,我添加了级联属性:

oneToMany:
    images:
        targetEntity: MyBundle\Entity\ProductImage
        mappedBy: product
        orderBy:
            position: ASC
        cascade: ["persist"]

这让它工作了(或者我是这么认为的),但我注意到数据库中的product_id 设置为NULL。我通过在ProductAdmin 类中添加prePersist()preUpdate() 方法解决了这个问题:

public function prePersist($object)

    foreach ($object->getImages() as $image) 
        $image->setProduct($object);
    


public function preUpdate($object)

    foreach ($object->getImages() as $image) 
        $image->setProduct($object);
    

...并在Product 实体的addImages() 方法中添加了一行:

public function addImage(\MyBundle\Entity\ProductImage $images)

    $images->setProduct($this);
    $this->images[] = $images;

    return $this;

这对我有用,现在我可以在我的产品中添加、更改、重新排序、删除等图像。

【讨论】:

漂亮的答案,您对 prePersist 和 preUpdate 函数的使用非常完美。

以上是关于如何在GridView中实现多选的主要内容,如果未能解决你的问题,请参考以下文章

我应该如何在角度材料中实现多项选择选项?

FileUpload1 在部分浏览器中实现多选

Extjs中Grid中实现多选,相当于按着Ctrl键实现多选

如何在angular js中实现多路由

如何在 PostgreSQL 中实现多对多关系?

如何在 laravel 护照中实现多身份验证