Showing posts with label ReadOnlyAttribute. Show all posts
Showing posts with label ReadOnlyAttribute. Show all posts

Wednesday, 28 January 2009

Making Individual Tables Read Only – Dynamic Data

These are two thing you can do to make your table Read Only.

  1. Add an attribute for instance the ReadOnlyAttribute or your own custom attribute
  2. Using Routing to restrict access to the Edit or Insert pages

The first solution I covered in this article Writing Attributes and Extension Methods for Dynamic Data so I’ll just show the Routing example here.

// Setting a table to Read only
var visibleTables = from t in MetaModel.Default.Tables
                    where t.Scaffold == true
                    select t;

var readOnlyTables = new StringBuilder();
foreach (var table in visibleTables)
{
    var isReadOnly = table.Attributes.OfType<ReadOnlyAttribute>().
DefaultIfEmpty(new ReadOnlyAttribute(false)).
FirstOrDefault();
    if (isReadOnly.IsReadOnly)
        readOnlyTables.Append(table.Name + "|");
}

routes.Add(new DynamicDataRoute("{table}/{action}.aspx")
{
    Constraints = new RouteValueDictionary(new
    {
        action = "Edit|Insert",
        table = readOnlyTables.ToString().Substring(0, readOnlyTables.Length - 1)
    }),
    ViewName = "Details",
    Model = model
});

Listing 1 – Routing example.

[ReadOnly(true)]
public partial class Employee {}

Listing 2 – sample attribute.

In Listing 1 we see three things going on:

  1. We get a list of visible tables using the Scaffold attribute to find out if the table should be shown.
  2. Next we loop through the visible tables and if the table is set to ReadOnly then we add it to the readOnlyTables StringBuilder to build a list of read only tables (e.g. “Products|Customers”).
  3. Build a route that constrains the these tables to only get to the Details page.
Note: That this route must appear before the default routes.

Happy coding and remember your a PC HappyWizard but for us coders I prefer the short lived “Live to Code and Code to Live”

Important: The only caveat here is that the Delete button still works. :( But you could catch that in Business logic if you didn’t want to edit each page.

Friday, 23 January 2009

Making a Field Read-Only via the ReadOnlyAttribute – Dynamic Data

This article is as a result of this thread not editable attribute on the Dynamic Data Forum:

What you need to do is:

  1. Use the ReadOnlyAttribute in System.ComponentModel and attribute up the column you want as read only in edit mode

  2. Create an class that implements IAutoFieldGenrator.

  3. A custom DynamicField.

And here's the sample:

using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Web.DynamicData;
using System.Web.UI;
using System.Web.UI.WebControls;

public class FieldsManager : IAutoFieldGenerator
{
    protected MetaTable _table;

    public FieldsManager(MetaTable table)
    {
        _table = table;
    }

    public ICollection GenerateFields(Control control)
    {
        var oFields = new List<DynamicField>();

        foreach (var column in _table.Columns)
        {
            // carry on the loop at the next column  
            // if scaffold table is set to false or DenyRead
            if (!column.Scaffold || column.IsLongString)
                continue;

            DynamicField f;

            // here we check to dee
            if (column.Attributes.OfType<ReadOnlyAttribute>().
DefaultIfEmpty(new ReadOnlyAttribute(false)).
FirstOrDefault().IsReadOnly) f = new DynamicReadonlyField(); else f = new DynamicField(); f.DataField = column.Name; oFields.Add(f); } return oFields; } } // special thanks to david Ebbo for this public class DynamicReadonlyField : DynamicField { public override void InitializeCell( DataControlFieldCell cell, DataControlCellType cellType, DataControlRowState rowState, int rowIndex) { if (cellType == DataControlCellType.DataCell) { var control = new DynamicControl() { DataField = DataField }; // Copy various properties into the control control.UIHint = UIHint; control.HtmlEncode = HtmlEncode; control.NullDisplayText = NullDisplayText; // this the default for DynamicControl and has to be // manually changed you do not need this line of code // its there just to remind us what we are doing. control.Mode = DataBoundControlMode.ReadOnly; cell.Controls.Add(control); } else { base.InitializeCell(cell, cellType, rowState, rowIndex); } } }

And in the Edit page add:

protected void Page_Init(object sender, EventArgs e)
{
    DynamicDataManager1.RegisterControl(DetailsView1);
    table = DetailsDataSource.GetTable();
    DetailsView1.RowsGenerator = new FieldsManager(table);
}

In the Page_Init add the BOLD ITALIC lines

This is a direct copy of the answer I gave in the thread HappyWizard