Tuesday, January 10, 2012

DataRelation with Multiple Columns in C# ADO.NET


ADO.NET's DataRelation Object

Joining Tables the .NET Way

by William Ryan
Print this ArticleDiscuss in Forums

As I've mentioned before, of all of the areas where things have changed in .NET, ADO.NET is probably the biggest (at least it's one of the top 3).  In classic ADO, there weren'tDataSets , DataTables or  most other ADO.NET objects.  In classic ADO, if you needed to join two tables, typically you'd write the SQL statement and include the join and pull back all of the data.  By very definition, you are pulling back redundant data when you use this method.  This has many drawbacks to it, the most striking of which is performance - after all, it takes a lot longer to pull back Xmb of data than it does X/10mb of data.  This is where ADO.NET really shines.  But, if you don't join your tables and pull them into a recordset, how do you get the data back?  In comes the DataRelation.

This isn't a really difficult concept, but if you aren't familiar with DataSets and DataTables, I'd suggest you read up on before continuing.  To begin with, I'm going to assume that you have two tables, Transactions and TransactionDetails.  They have a bunch of fields in them, but they are related by a common field, TransactionID.  So, the first thing you'd do is pull back all of the relevant data from both tables:
DataSet ds = new DataSet();
SqlConnection cn = new SqlConnection(
ConfigurationSettings.AppSettings("ConnectString"));SqlCommand cmd = new SqlCommand("usp_FillTransactions", cn);
cmd.CommandType = CommandType.StoredProcedure;
SqlDataAdapter daTransactions = new SqlDataAdapter(cmd);
daTransactions.Fill(ds, "Transactions");  //pass in ds as DataSet, and "Transactions" as the table name

SqlCommand cmdDetails = new SqlCommand("usp_FillTransactionDetails", cn);
cmd.CommandType = CommandType.StoredProcedure;
SqlDataAdapter daTransactionDetails = new SqlDataAdapter(cmdDetails);
daTransactionDetails.Fill(ds, "Details");


Ok, now I have the complete Transactions table and the TransactionDetails table loaded into my DataSet (remember that the DataSet is an approximate abstraction of your database, so you wouldn't normally need more than one for any given app unless the data is coming from different databases).

But, if I were to bind some controls to Transactions and a grid to TransactionDetails without doing anything else, every time I navigated to a different record, Details wouldn't have any idea of what Transactions is doing and vice versa.  In order the bind these two to each other, you need to use a DataRelation. So what benefits are we going to derive from this?  The first is performance, we will pull over much less data as opposed to using a server side join.  The second is validation.  Once we add the Relation, we don't have to worry about deleting child records that don't have parents or inserting detail records without a valid Transaction.  The third is easy of navigation.  Once we Relate these tables, a BindingManagerBase or a BindingContext will automatically reposition the child records whenever the parent changes. Moreoever, we can propogate any changes in the parent table (Transaction) to the Child (TransactionDetails).  The importance of this can not be understated.  If set up correctly, the programmer doesn't have to worry about writing all the validation code and missing something.  It's also a lot easier to write 5 lines of code than it is to roll out your own validation logic (when I speak of validation, I'm referring to it at the database level, you will probably still want to let the users know when they put a Name in a Date field for instance).  Moreoever, you don't have to write update logic for this other than the update logic that your DataAdapter employs.  You can do it the hard way and ignore the DataRelation, but in all likelihood you'll overlook something that you never intended to occur and risk dealing with bad data in your database.  Finally, after the initial performance hit of loading your data (the DataRelation doesn't cause this) which would occur either way, you can show 'child' records without having to requery your database.  In every conceivable way, performance will be improved and you will limit possible data errors.  And even if you think you can write better code than the well tested DataRelation, the beauty of it is that it doesn't prohibit you from adding your own validation.  So regardless of your goal, you can use the DataRelation to your advantage.

Hopefully I sold you on the benefits of this (if not, drop me an email at bill@knowdotnet.com and I can send you copies of about 50 emails I've received from people who refused to use the DataRelation, asked me for help and swear by it now) really great object but you are probably asking, how do I use it?  Here it goes:

There are 5 constructors that can model just about anything you have in your database schema.  I've heard many people say they don't use DataRelations b/c they haveCompound Keys in their Schema, but as you'll see, this criticism holds no water.  The first constructor is probably the one you'll use most often.  In our example above, we have TransactionID as a Primary key in the parent table and as it serves as the Foreign Key in the child table.

To build this, we pass in the name we want to use to refer to the relation (just like you name your Relations in SQL Server or Oracle), the Parent Column and the Child Column:

VB.NET:

'For simple single column relation

Dim Tran_Detail as New DataRelation("ds", ds.Tables(0).Columns("TransID"), ds.Tables(1).Columns("TransID"))

You can also use all Ordinal references or mix them as you see fit.  Assuming that TransID was the first column in both Datatables, the following would work the same:

Dim Tran_Detail as New DataRelation("MyRelationName", ds.Tables("Transactions").Columns(0), ds.Tables("Details").Columns(0)) 'or
Dim Tran_Detail as New DataRelation("MyRelationName", ds.Tables(0).Columns(0), ds.Tables(1).Columns(0))

'Finally
ds.Relations.Add(Tran_Detail)


C#

DataRelation Tran_Detail = new DataRelation("ds", ds.Tables[0].Columns["TransID"], ds.Tables[1].Columns["TransID"]);
//For the sake of brevity I'm not going to translate each of the above, but you can switch between the nominal or the ordinal and provided
//you use the correct index, it will work the same
ds.Relations.Add(Tran_Detail);

Like I said, this is the simplest of the constructors. The other overloads are provided below:

DataRelation(string, ParentDataColum(), ChildDataColumn())  'this takes an array of DataColumns, so you could use this constructor the same way we did above

DataRelation(string, ParentDataColumn, ChildDataColumn, Boolean) //Where the boolean instructs the DataRelation whether or not to enforce //the constraints.  For good reason Constraints are enabled by default, and I'd recommend against setting this to false unless you have a //really good reason to do so...and if you do, don't complain to me when a user does something you didn't intend and your validation code //misses it.

//Similarly, there is an Array Based constructor with the Boolean:

DataRelations(string, ParentDataColumn(), ChildDataColumn(), Boolean)
//this is identical to the one above it except it allows the use of multiple columns aka Composite Keys

The final constructor allows you to simply name the tables and the columns, but this will already be done most of the time.  For that reason, I'm not going to address, but it's Here if you find the need to use it.


This is pretty much all there is to it at this point, but I'd like to mention two other things.  First, if you don't supply a name for the DataRelation (you still have to declare it and give the variable name, but the first parameter in each constructor is the name that you can also use to reference it), it will supply one for you.  Don't do this!  While it will compile  and work, more than likely it's going to confuse you, and you can bet it will confuse the next guy who uses your code.  Second, you can have multiple DataRelations in a DataSet.  If you think about it, it would be pretty lame if you could only have one relation in an entire DataSet.  However, you  can't have multiple datarelations between dataset.  Stated simply, If I had 4 tables, Transactions & Details, Customers & ContactHistory, I could have a relation between Transactions and Details as well as one between Customers and ContactHistory in the same Dataset.  But I couldn't have 2 Relations between Transactions and Details (and since you can use Compound Keys, there is absolutely no reason to do so).

Ok, so how do you use the other constructors?  Let's say that instead of having only TransID as the Key in both tables, let's say that we had a compoun key, TransID, CustomerID and SalePersonID.  All three fields exist in both tables.  And since we are responsible programmers, we are going to leave the EnforceConstraints property where it should be , ON.

Here's how we'd do it:

VB.NET

'Declare the Columns - even though we have multiple fields, we only have two tables, hence TransactionColumns and DetailColumns
Dim TransactionColumns() as DataColumn
Dim DetailColumns() as DataColumn

TransactionColumns = New DataColum(){ds.Tables(0).Columns("TransID"), ds.Tables(0).Columns("CustomerID"), ds.Tables(0).Columns("SalePersonID")}
DetailColumns = New DataColumns(){ds.Tables(1).Columns("TransID"), ds.Tables(1).Columns("CustomerID"), ds.Tables(1).Columns("SalesPersonID")}
'We could also use all norminals, ordinals or any mixture of them

'Add the name and DataColumn arrays to the Relation
Dim Tran_Detail as New DataRelation("myRelationName", TransActionColumns, DetailColumns)
'Add the Relation to the DataSet
ds.Relations.Add(Tran_Detail)


C#

DataColumn[] TransactionColumns;
DataColumn[] DetailColumns;

TransactionColumns = new DataColumn[] {ds.Tables[0].Columns["TransID"], ds.Table[0].Columns["CustomerID"], ds.Tables[0].Columns["SalePersonID"]};
DetailColumns = new DataColumn[] {ds.Tables[1].Columns["TransID"], ds.Table[1].Columns["CustomerID"], ds.Tables[1].Columns["SalePersonID"]};

DataRelation Tran_Detail = new DataRelation("myDataRelation", TransactionColumns, DetailColumns);
ds.Relations.Add(Tran_Detail);


Now, we could use the exact same code and specify the EnableConstraints Property to either false or true.  To do this, none of the code above would change except for the code in the constructor, to which you'd add a true or false parameter:

VB.NET

Dim Tran_Detail as New DataRelation("myRelationName", TransActionColumns, DetailColumns, True)


C#

DataRelation Tran_Detail = new DataRelation("myDataRelation", TransactionColumns, DetailColumns, true);

One last thing before I wrap it up.  I left out the more complex constructor which is somewhat more complex because while it's simple to implement, understanding it conceptually isn't.  I think you need to fully understand DataRelations before you go diving  into scenarios where you are nesting relations.  A common scenario where you'd use such a technique could include a case where TransDetails had a child table called PayementDetails.  When you iterate through Transactions, you might have a grid which would display the TransDetails but you might have another grid or tab that displayed the payment details of each of the Transaction Details.  In properly normalized data, this is something you'll probably run across, but you can still accomplish what I just mentioned using standard relations.  I've used these on a few occassions and think they are pretty straighforward, but given the fact that many people have trouble getting composite keys to work, I opted to leave this out of the discussion.  I've got a few code examples and if you are interested in seeing how this works, email me  Here and I'll send them to you.

Conclusion:

There are many reasons to use DataRelations and very few not to, in fact I can think of only one. Here are the big ones that I can think of:

1)  They enforce integrity!  Since this is a fundamental goal  of any true Relational Database, this alone is enough.  And while you think you can roll out your own logic, do yourself a favor and use these.  If you really think you can do a better job, you can still include your own validation code...but don't ignore these.  They'll cascade your changes, they'll propogate updates (for instance, if you get an Identity value back from your database and update the parent column, the children will be updated too), they are simple to use and they are powerful
2)  They make otherwise difficult navigation much easier.  In fact, if you don't use them, you'll have to constantly requery your database to the child values, and this causes unnecessary strain on the database, network and client machine.  In addition, if you requery your database each time a change occurs, you are limiting your applications ability to operate in disconnected scenarios which has no upside
3)  They are faster and more efficient than other approaches.  Since you have reduced network traffic and fire fewer queries, your app will repond quicker
4)  They can handle just about anything you can throw at them.  The DataColumn is a very powerful object and combined with a DataRelation, you can support composite keys, Auto Increment fields, and just about anything else you might throw at it.

The only downside I can see is that if you aren't using a BindingContext or a BindingManager, navigation isn't automatic as far as filtering goes.  However, this is a very small issue overall, and when compared to the benefits you gain, it's inconsequential.

Wednesday, December 21, 2011

DataView RowFilter Examples


DataView RowFilter Syntax [C#]

This example describes syntax of DataView.RowFil­ter expression. It shows how to correctly build expression string (without „SQL injection“) using methods to escape values.

Column names

If a column name contains any of these special characters ~ ( ) # \ / = > < + - * % & | ^ ' " [ ], you must enclose the column name within square brackets [ ]. If a column name contains right bracket ] or backslash \, escape it with backslash (\] or \\).
[C#]
dataView.RowFilter = "id = 10";      // no special character in column name "id"
dataView.RowFilter = "$id = 10";     // no special character in column name "$id"
dataView.RowFilter = "[#id] = 10";   // special character "#" in column name "#id"
dataView.RowFilter = "[[id\]] = 10"; // special characters in column name "[id]"

Literals

String values are enclosed within single quotes ' '. If the string contains single quote ', the quote must be doubled.
[C#]
dataView.RowFilter = "Name = 'John'"        // string value
dataView.RowFilter = "Name = 'John ''A'''"  // string with single quotes "John 'A'"

dataView.RowFilter = String.Format("Name = '{0}'", "John 'A'".Replace("'", "''"));

Number values are not enclosed within any characters. The values should be the same as is the result of int.ToString() or float.ToString() method for invariant or English culture.
[C#]
dataView.RowFilter = "Year = 2008"          // integer value
dataView.RowFilter = "Price = 1199.9"       // float value

dataView.RowFilter = String.Format(CultureInfo.InvariantCulture.NumberFormat,
                     "Price = {0}", 1199.9f);

Date values are enclosed within sharp characters # #. The date format is the same as is the result of DateTime.ToString() method for invariant or English culture.
[C#]
dataView.RowFilter = "Date = #12/31/2008#"          // date value (time is 00:00:00)
dataView.RowFilter = "Date = #2008-12-31#"          // also this format is supported
dataView.RowFilter = "Date = #12/31/2008 16:44:58#" // date and time value

dataView.RowFilter = String.Format(CultureInfo.InvariantCulture.DateTimeFormat,
                     "Date = #{0}#", new DateTime(2008, 12, 31, 16, 44, 58));

Alternatively you can enclose all values within single quotes ' '. It means you can use string values for numbers or date time values. In this case the current culture is used to convert the string to the specific value.
[C#]
dataView.RowFilter = "Date = '12/31/2008 16:44:58'" // if current culture is English
dataView.RowFilter = "Date = '31.12.2008 16:44:58'" // if current culture is German

dataView.RowFilter = "Price = '1199.90'"            // if current culture is English
dataView.RowFilter = "Price = '1199,90'"            // if current culture is German

Comparison operators

Equal, not equal, less, greater operators are used to include only values that suit to a comparison expression. You can use these operators = <> < <= > >=.
Note: String comparison is culture-sensitive, it uses CultureInfo from DataTable.Localeproperty of related table (dataView.Table.Locale). If the property is not explicitly set, its default value is DataSet.Locale (and its default value is current system culture Thread.Curren­tThread.Curren­tCulture).
[C#]
dataView.RowFilter = "Num = 10"             // number is equal to 10
dataView.RowFilter = "Date < #1/1/2008#"    // date is less than 1/1/2008
dataView.RowFilter = "Name <> 'John'"       // string is not equal to 'John'
dataView.RowFilter = "Name >= 'Jo'"         // string comparison

Operator IN is used to include only values from the list. You can use the operator for all data types, such as numbers or strings.
[C#]
dataView.RowFilter = "Id IN (1, 2, 3)"                    // integer values
dataView.RowFilter = "Price IN (1.0, 9.9, 11.5)"          // float values
dataView.RowFilter = "Name IN ('John', 'Jim', 'Tom')"     // string values
dataView.RowFilter = "Date IN (#12/31/2008#, #1/1/2009#)" // date time values

dataView.RowFilter = "Id NOT IN (1, 2, 3)"  // values not from the list

Operator LIKE is used to include only values that match a pattern with wildcards. Wildcardcharacter is * or %, it can be at the beginning of a pattern '*value', at the end 'value*', or at both '*value*'. Wildcard in the middle of a patern 'va*lue' is not allowed.
[C#]
dataView.RowFilter = "Name LIKE 'j*'"       // values that start with 'j'
dataView.RowFilter = "Name LIKE '%jo%'"     // values that contain 'jo'

dataView.RowFilter = "Name NOT LIKE 'j*'"   // values that don't start with 'j'

If a pattern in a LIKE clause contains any of these special characters * % [ ], those characters must be escaped in brackets [ ] like this [*][%][[] or []].
[C#]
dataView.RowFilter = "Name LIKE '[*]*'"     // values that starts with '*'
dataView.RowFilter = "Name LIKE '[[]*'"     // values that starts with '['

The following method escapes a text value for usage in a LIKE clause.
[C#]
public static string EscapeLikeValue(string valueWithoutWildcards)
{
  StringBuilder sb = new StringBuilder();
  for (int i = 0; i < valueWithoutWildcards.Length; i++)
  {
    char c = valueWithoutWildcards[i];
    if (c == '*' || c == '%' || c == '[' || c == ']')
      sb.Append("[").Append(c).Append("]");
    else if (c == '\'')
      sb.Append("''");
    else
      sb.Append(c);
  }
  return sb.ToString();
}

[C#]
// select all that starts with the value string (in this case with "*")
string value = "*";
// the dataView.RowFilter will be: "Name LIKE '[*]*'"
dataView.RowFilter = String.Format("Name LIKE '{0}*'", EscapeLikeValue(value));

Boolean operators

Boolean operators ANDOR and NOT are used to concatenate expressions. Operator NOT has precedence over AND operator and it has precedence over OR operator.
[C#]
// operator AND has precedence over OR operator, parenthesis are needed
dataView.RowFilter = "City = 'Tokyo' AND (Age < 20 OR Age > 60)";

// following examples do the same
dataView.RowFilter = "City <> 'Tokyo' AND City <> 'Paris'";
dataView.RowFilter = "NOT City = 'Tokyo' AND NOT City = 'Paris'";
dataView.RowFilter = "NOT (City = 'Tokyo' OR City = 'Paris')";
dataView.RowFilter = "City NOT IN ('Tokyo', 'Paris')";

Arithmetic and string operators

Arithmetic operators are addition +, subtraction -, multiplication *, division / and modulus %.
[C#]
dataView.RowFilter = "MotherAge - Age < 20";   // people with young mother
dataView.RowFilter = "Age % 10 = 0";           // people with decennial birthday

There is also one string operator concatenation +.

Parent-Child Relation Referencing

parent table can be referenced in an expression using parent column name with Parent.prefix. A column in a child table can be referenced using child column name with Child. prefix.
The reference to the child column must be in an aggregate function because child relationships may return multiple rows. For example expression SUM(Child.Price) returns sum of all prices in child table related to the row in parent table.
If a table has more than one child relation, the prefix must contain relation name. For example expression Child(OrdersToItemsRelation).Price references to column Price in child table using relation named OrdersToItemsRe­lation.

Aggregate Functions

There are supported following aggregate functions SUMCOUNTMINMAXAVG (average), STDEV(statistical standard deviation) and VAR (statistical variance).
This example shows aggregate function performed on a single table.
[C#]
// select people with above-average salary
dataView.RowFilter = "Salary > AVG(Salary)";

Following example shows aggregate functions performed on two tables which have parent-child relation. Suppose there are tables Orders and Items with the parent-child relation.
[C#]
// select orders which have more than 5 items
dataView.RowFilter = "COUNT(Child.IdOrder) > 5";

// select orders which total price (sum of items prices) is greater or equal $500
dataView.RowFilter = "SUM(Child.Price) >= 500";

Functions

There are also supported following functions. Detailed description can be found hereDataColumn.Ex­pression.
  • CONVERT – converts particular expression to a specified .NET Framework type
  • LEN – gets the length of a string
  • ISNULL – checks an expression and either returns the checked expression or a replacement value
  • IIF – gets one of two values depending on the result of a logical expression
  • TRIM – removes all leading and trailing blank characters like \r, \n, \t, ‚ ‘
  • SUBSTRING – gets a sub-string of a specified length, starting at a specified point in the string

Wednesday, December 14, 2011

PageMethods undefined,MasterPage PageMethods


ScriptManager and MasterPage PageMethods !

I know that this subject has been asked many times therefore i would like to summarize it and give a small tutorial about how to do it.
I had some PageMethods on a default page which calls some web methods on code behind of the page. Before 1 week we decided to change the old structure of the project UI to use MasterPage. MaterPage triggered many problems with it, one of these problems that MasterPage does not support JS PageMethods! because MasterPage does not inherit from Web.UI.Page therefore you can not call PageMethods (its not a page!) – you can not call pagemethods on usercontrols too – so handle this problem and call your methods you can try this tutorial;
  • Create a MasterPage and add a ScriptManager on page.
  • On ScriptManager add the folowings
       1:  <asp:ScriptManager ID="ScriptManager" runat="server"
                   EnableScriptGlobalization="true"
       2:          LoadScriptsBeforeUI="true" 
                             EnableScriptLocalization="true" 
                             EnablePageMethods="true">
       3:         <Scripts>
       4:              <asp:ScriptReference 
                          Path="~/Javascript/MasterPageWSJS.js" />
       5:          </Scripts>
       6:          <Services>
       7:              <asp:ServiceReference 
                           Path="~/WebServices/MasterPageWS.asmx" />
       8:          </Services>
       9:      </asp:ScriptManager>
        Here we have 2 important sections
                   - Scritps which includes our JS file location
                   - Sevices which includes our Webservices location
       Here to be mentioned that EnablePageMethods attribute means nothing on MasterPages!.
  • Add a javascript file to the project ( here its  MasterPageWSJS.js)
       1:  function CallService() {
       2:  //CallFromMasterJS() is the name of the service method
       3:            MasterPageWS.CallFromMasterJS();
       4:    }
  • Add a Webservice file to the project (here it is MasterPageWS.asmx)
       1:  <%@ WebService Language="C#" Class="MasterPageWS" %>
       2:   
       3:  using System;
       4:  using System.Web;
       5:  using System.Web.Services;
       6:  using System.Web.Services.Protocols;
       7:  using System.Web.Script.Services;
       8:   
       9:  [WebService(Namespace = "http://tempuri.org/")]
      10:  [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
      11:  [ScriptService]
      12:  public class MasterPageWS : System.Web.Services.WebService
      13:  {
      14:   
      15:      [WebMethod(EnableSession = true)]
      16:      public void CallFromMasterJS()
      17:      {
      18:   // todo: write the needed codes
      19:      }
      20:  }
Here some important notes about the service:
- decorate the service class with [ScriptService]
- Decorate your methods with [WebMethod] add if you want to use
session variables with it decorate it with
[WebMethod(EnableSession = true)] because webservices are
stateless by default
  • at the end add this code lines to your MasterPage codebehind:
       1:  if(!IsPostBack)
       2:  {
       3:  // masterBody is the ID of the masterpage body html tag       
            HtmlGenericControl body = 
          (HtmlGenericControl)Page.Master.FindControl("masterBody");
       4:          body.Attributes.Add("onunload", "CallService();");
       5:  }
That is all !. when you start your page and refresh it the master page will unloaded and that will fire the event onunload on the page body which will call the JS and from there the web service will be called.


Source:  Click here

Wednesday, December 7, 2011

A potentially dangerous Request.Form value was detected from the client


A potentially dangerous Request.Form value was detected from the client (Login1$txtUserName="<html>").

Description: Request Validation has detected a potentially dangerous client input value, and processing of the request has been aborted. This value may indicate an attempt to compromise the security of your application, such as a cross-site scripting attack. To allow pages to override application request validation settings, set the requestValidationMode attribute in the httpRuntime configuration section to requestValidationMode="2.0". Example: <httpRuntime requestValidationMode="2.0" />. After setting this value, you can then disable request validation by setting validateRequest="false" in the Page directive or in the <pages> configuration section. However, it is strongly recommended that your application explicitly check all inputs in this case. For more information, see http://go.microsoft.com/fwlink/?LinkId=153133.

Exception Details: System.Web.HttpRequestValidationException: A potentially dangerous Request.Form value was detected from the client (Login1$txtUserName="<html>").




Solution:
 ==========
                       Insert the following lines in your web.config 

 

 <system.web>


 <pages validateRequest="false">

    </pages>


//If your using .NET 4.0 use the following attribute
  <httpRuntime requestValidationMode="2.0" />
 </system.web>


Wednesday, November 16, 2011

How To Set Time Zone using Command Prompt in Windows

Changing the time zone through the clock is very easy in Windows 7. You need to simply click on the clock present on the taskbar notification area and click on “Change date and time settings…“. But do you know that Windows 7 also provides a command line utility to change your present time zone? Bet you don’t!
The command line utility that helps you change the time zone in Windows 7 is tzutil.exe and is known as Windows Time Zone Utility. This is a great for all the people who prefers working from the command prompt.
There are three tzutil parameters, each of which is described below:
tzutil.exe
To change the time zone, use the /s parameter. For example, tzutil /s "universal standard time".
To display the current time zone, use the /g parameter. For example, tzutil /g.
To get a list of all available time zones, use the /l parameter. For example, tzutil /l.

Find the following "bat"  file.
====================
Download TimeZone Change file

Out put  :
======
1. Change your current time to zone some other time zone.
2. Run the above downloaded "TimezoneChange.bat" file.
3. Withing five min your time zone will be change to "Indian Standard Time".




Friday, November 11, 2011

How to hide/disable Day/Month/WorkWeek/Timeline views in devexpress Aspxscheduler


How to hide DayView/WorkWeekView/Month View/Timeline Views in deexpress ASPxScheduler.
How to disable DayView/WorkWeekView/Month View/Timeline Views in deexpress ASPxScheduler.

Here schTaskCalendar is ASPxScheduler ID which is used in our requirement

Use the following code lines in your Page_Load. it will hides/disables  DayView/WorkWeekView from your ASPxScheduler control.

Code:

protected void Page_Load(object sender, EventArgs e)
{
  DevExpress.Web.ASPxScheduler.SchedulerViewRepository baseviews = schTaskCalendar.Views;
            baseviews.DayView.Enabled = false;
            baseviews.WorkWeekView.Enabled = false;
}