Supporting nested elements in ASP.Net Custom Server Controls - asp.net

I want to create a custom server control which looks like this:
<cc:MyControl prop1="a" prop2="b">
<cc:MyItem name="xxx">
<cc:MyItem name="yyy">
<cc:MyItem name="zzz">
</cc:MyControl>
MyControl is of course implemented as a server control, however I do not want MyItem to be child controls. Rather they should exist as simple .Net objects. I have a class called MyItem, and the control has a property called Items, and when MyItem elements are declared in the markup, the objects should be instantiated and added to the collection.
The tutorials on MSDN don't actually explain how this happens. See: http://msdn.microsoft.com/en-us/library/9txe1d4x.aspx
I'd like to know:
How is <cc:MyItem> mapped to the MyItem class? Does the element in the markup have to have the same name as the object's class?
Which constructor of MyItem is called when MyItems are added declaratively, and when?
What collection types am I permitted to use to hold MyItem objects? The link above uses ArrayList, but can I use the strongly typed List instead?
Is it possible for a control to contain multiple collections?

It is so common to use class name for markup, but you can assign another name if you want, I do not explain more, if you want please comment
when asp.net compiles markup, it uses default parameter less constructor
you can use any collection type but if you want to use benefits of viewstate your collection type must implement IStateManager interface (below I wrote source of collection that I created for my self with state managing support)
Yes, your control can have multiple collections, just add required attributes as below:
(I used one of my codes, please replace names with your desired name)
if you want to have collection first of all you must define its property in your control.
imagine we have a control named CustomControl that extends Control as below:
[System.Web.UI.ParseChildrenAttribute(true)]
[System.Web.UI.PersistChildrenAttribute(false)]
public class CustomControl : Control{
private GraphCollection m_graphs;
[Bindable(false)]
[Category("Appearance")]
[DefaultValue("")]
[Localizable(true)]
[PersistenceMode(PersistenceMode.InnerProperty)]
public GraphCollection Graphs
{
get
{
if (this.m_graphs == null) {
this.m_graphs = new GraphCollection();
if (base.IsTrackingViewState) {
this.m_graphs.TrackViewState();
}
}
return this.m_graphs;
}
}
}
as you can see in above code, CustomControl has a field with name "m_graphs" with type of "GraphCollection", also a property that exposes this field
also please please pay attention to its attribute PersistenceMode that says to asp.net property "Graphs" must persisted as InnerProperty
also please pay attention to two attributes applied to CustomControl class
attribute ParseChildrenAttribute says to asp.net that nested markup, must be treated as properties and attribute PersistChildrenAttribute says to asp.net that nested markups are not control's children
at the final, I bring two source codes for state managing components
first of all GraphCollection that extends from StateManagedCollection (both classes was written by me)
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web.UI;
namespace Farayan.Web.Core
{
public class StateManagedCollection<T> : IList, ICollection, IEnumerable, IEnumerable<T>, IStateManager
where T : class, IStateManager, new()
{
// Fields
private List<T> listItems = new List<T>();
private bool marked = false;
private bool saveAll = false;
// Methods
public void Add(T item)
{
this.listItems.Add(item);
if (this.marked) {
//item.Dirty = true;
}
}
public void AddRange(T[] items)
{
if (items == null) {
throw new ArgumentNullException("items");
}
foreach (T item in items) {
this.Add(item);
}
}
public void Clear()
{
this.listItems.Clear();
if (this.marked) {
this.saveAll = true;
}
}
public bool Contains(T item)
{
return this.listItems.Contains(item);
}
public void CopyTo(Array array, int index)
{
this.listItems.CopyTo(array.Cast<T>().ToArray(), index);
}
public IEnumerator GetEnumerator()
{
return this.listItems.GetEnumerator();
}
public int IndexOf(T item)
{
return this.listItems.IndexOf(item);
}
public void Insert(int index, T item)
{
this.listItems.Insert(index, item);
if (this.marked) {
this.saveAll = true;
}
}
public void LoadViewState(object state)
{
object[] states = state as object[];
if (state == null || states.Length == 0)
return;
for (int i = 0; i < states.Length; i++) {
object itemState = states[i];
if (i < Count) {
T day = (T)listItems[i];
((IStateManager)day).LoadViewState(itemState);
} else {
T day = new T();
((IStateManager)day).LoadViewState(itemState);
listItems.Add(day);
}
}
}
public void Remove(T item)
{
int index = this.IndexOf(item);
if (index >= 0)
this.RemoveAt(index);
}
public void RemoveAt(int index)
{
this.listItems.RemoveAt(index);
if (this.marked) {
this.saveAll = true;
}
}
public object SaveViewState()
{
List<object> state = new List<object>(Count);
foreach (T day in listItems)
state.Add(((IStateManager)day).SaveViewState());
return state.ToArray();
}
int IList.Add(object item)
{
T item2 = (T)item;
this.listItems.Add(item2);
return listItems.Count - 1;
}
bool IList.Contains(object item)
{
return this.Contains((T)item);
}
int IList.IndexOf(object item)
{
return this.IndexOf((T)item);
}
void IList.Insert(int index, object item)
{
this.Insert(index, (T)item);
}
void IList.Remove(object item)
{
this.Remove((T)item);
}
void IStateManager.LoadViewState(object state)
{
this.LoadViewState(state);
}
object IStateManager.SaveViewState()
{
return this.SaveViewState();
}
void IStateManager.TrackViewState()
{
this.TrackViewState();
}
public void TrackViewState()
{
this.marked = true;
for (int i = 0; i < this.Count; i++) {
((IStateManager)this[i]).TrackViewState();
}
}
// Properties
public int Capacity
{
get
{
return this.listItems.Capacity;
}
set
{
this.listItems.Capacity = value;
}
}
public int Count
{
get
{
return this.listItems.Count;
}
}
public bool IsReadOnly
{
get
{
return false;
}
}
public bool IsSynchronized
{
get
{
return false;
}
}
public T this[int index]
{
get
{
return (T)this.listItems[index];
}
}
public object SyncRoot
{
get
{
return this;
}
}
bool IList.IsFixedSize
{
get
{
return false;
}
}
object IList.this[int index]
{
get
{
return this.listItems[index];
}
set
{
this.listItems[index] = (T)value;
}
}
bool IStateManager.IsTrackingViewState
{
get
{
return this.marked;
}
}
#region IEnumerable<T> Members
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return this.listItems.GetEnumerator();
}
#endregion
#region IEnumerable Members
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
#endregion
}
}
and GraphCollection
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Farayan.Web.Core;
namespace Farayan.Web.AmCharts
{
public class GraphCollection : StateManagedCollection<Graph>
{
}
}
and finally Graph in our example:
using System;
using System.Linq;
using System.Collections.ObjectModel;
using System.Drawing;
using System.Web.UI;
using System.ComponentModel;
using Farayan.Web.AmCharts;
using System.Collections.Generic;
using Farayan.Web.Controls;
using System.Runtime;
using Farayan.Web.Core;
namespace Farayan.Web.AmCharts
{
public class Graph : StateManager
{
#region Colorize Property
[Browsable(true)]
[Localizable(false)]
[PersistenceMode(PersistenceMode.Attribute)]
[DefaultValue(false)]
public virtual bool Colorize
{
get { return ViewState["Colorize"] == null ? false : (bool)ViewState["Colorize"]; }
set { ViewState["Colorize"] = value; }
}
#endregion
//==============================
public override void LoadViewState(object state)
{
base.LoadViewState(state);
}
public override object SaveViewState()
{
return base.SaveViewState();
}
}
}
you may noticed that Graph extends StateManager class
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Web.UI;
using Farayan.Web.AmCharts;
namespace Farayan.Web.AmCharts
{
public class StateManager : IStateManager
{
protected StateBag ViewState = new StateBag();
#region IStateManager Members
public virtual bool IsTrackingViewState
{
get { return true; }
}
public virtual void LoadViewState(object state)
{
if (state != null) {
ArrayList arrayList = (ArrayList)state;
for (int i = 0; i < arrayList.Count; i += 2) {
string value = ((IndexedString)arrayList[i]).Value;
object value2 = arrayList[i + 1];
ViewState.Add(value, value2);
}
}
}
public virtual object SaveViewState()
{
ArrayList arrayList = new ArrayList();
if (this.ViewState.Count != 0) {
IDictionaryEnumerator enumerator = this.ViewState.GetEnumerator();
while (enumerator.MoveNext()) {
StateItem stateItem = (StateItem)enumerator.Value;
//if (stateItem.IsDirty) {
if (arrayList == null) {
arrayList = new ArrayList();
}
arrayList.Add(new IndexedString((string)enumerator.Key));
arrayList.Add(stateItem.Value);
//}
}
}
return arrayList;
}
public virtual void TrackViewState()
{
}
#endregion
#region IStateManager Members
bool IStateManager.IsTrackingViewState
{
get { return this.IsTrackingViewState; }
}
void IStateManager.LoadViewState(object state)
{
this.LoadViewState(state);
}
object IStateManager.SaveViewState()
{
return this.SaveViewState();
}
void IStateManager.TrackViewState()
{
this.TrackViewState();
}
#endregion
}
}

Related

Using SQLite-net-pcl and can't update the data

So i have this really annoying problem where i Can't seem to get it to update any of the databases i have created, whats worse the i can see the instance is showing the updated information but isn't applying it. I'm really new to this and is my first course project.
This is the code that is being used to update the data:
'''
using Project.Database;
using Project.DataClasses;
using Project.Pages.SuperPages;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Essentials;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace Project.Pages.UpdateDeleteListItem
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class UpdateDeleteList : ContentPage
{
private new readonly Label Title;
private Style LabelStyle;
private StoreDetails UpdateStoreDetails;
private Entry SNum;
private Entry SName;
private Entry SMName;
private Entry Addy;
public UpdateDeleteList(string pageType, object Item)
{
InitializeComponent();
BindingContext = Item;
UpdateStoreDetails = (StoreDetails)Item;
SetLabelStyle();
string titleMsg = "Update or Delete Selected " + pageType;
Frame frame = new Frame();
Label title = new Label() {Text = titleMsg };
Title = title;
StackLayout titleStack = new StackLayout() { Children = { Title } };
frame.Content = titleStack;
if (pageType == "Store")
{
StoreUDLItem(frame);
}
if (pageType == "Ticket")
{
TicketUDLItem(frame);
}
StylePage();
}
private void SaveButton_Clicked(object sender, EventArgs args)
{
if (StoreCheckValues() == true)
{
var store = SName;
var storeManager = SMName;
var storeNumber = SNum;
var address = Addy;
var storeDataAccess = new StoreDataAccess();
UpdateStoreDetails.StoreName = store.Text;
UpdateStoreDetails.StoreManger = storeManager.Text;
UpdateStoreDetails.StoreNumber = storeNumber.Text;
UpdateStoreDetails.Address = address.Text;
//MerchandiserKey = GetMerchId()
storeDataAccess.SaveStoreDetails(UpdateStoreDetails);
storeDataAccess.SaveAllStoreDetails();
}
'''
here is the data access methods:
'''
using Project.DataClasses;
using SQLite;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Text;
using Xamarin.Forms;
namespace Project.Database
{
class StoreDataAccess
{
private SQLiteConnection database;
private static object collisionLock = new object();
public ObservableCollection<StoreDetails> StoreDetails { get; set; }
public StoreDataAccess()
{
database = DependencyService.Get<IDatabaseConnection>().DbConnectionStore();
database.CreateTable<StoreDetails>();
this.StoreDetails = new ObservableCollection<StoreDetails>(database.Table<StoreDetails>());
//AddNewTicket(new Ticket ticket);
}
//add ticket method
public void AddNewStore(StoreDetails item)
{
this.StoreDetails.Add(item);
}
//retrieve ticket method
public StoreDetails GetStoreDetails(int id)
{
lock (collisionLock)
{
return database.Table<StoreDetails>().FirstOrDefault(StoreDetails => StoreDetails.StoreId == id);
}
}
//save ticket
public int SaveStoreDetails(StoreDetails storeDetailsInstance)
{
lock (collisionLock)
{
if (storeDetailsInstance.StoreId != 0)
{
database.Update(storeDetailsInstance);
return storeDetailsInstance.StoreId;
}
else
{
database.Insert(storeDetailsInstance);
return storeDetailsInstance.StoreId;
}
//database.Commit();
}
}
public void SaveAllStoreDetails()
{
lock (collisionLock)
{
foreach (var storeDetailsInstance in this.StoreDetails)
{
if (storeDetailsInstance.StoreId != 0)
{
database.Update(storeDetailsInstance);
}
else
{
database.Insert(storeDetailsInstance);
}
}
}
}
'''
This is the page that is sending the information to the first code block to bind the data too
'''
using Project.Database;
using Project.DataClasses;
using Project.Pages.UpdateDeleteListItem;
using SQLite;
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace Project.Pages.ListPages
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class StoreList : ContentPage
{
private ObservableCollection<StoreDetails> Items { get; set; }
private readonly StoreDataAccess storeDataAccess;
private readonly SQLiteConnection database;
public StoreList()
{
InitializeComponent();
storeDataAccess = new StoreDataAccess();
this.BindingContext = this.storeDataAccess;
Items = storeDataAccess.StoreDetails;
StoreView.ItemsSource = Items;
}
async void Handle_ItemTapped(object sender, ItemTappedEventArgs e)
{
if (e.Item == null) { return; }
else
{
//var id = Items[e.ItemIndex].StoreId;
await Navigation.PushAsync(new UpdateDeleteList("Store", e.Item));
//Deselect Item
((ListView)sender).SelectedItem = null;
}
}
//page reload handle
protected override void OnAppearing()
{
base.OnAppearing();
var dbName = "StoreListDatabase.db3";
var path = Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.Personal), dbName);
if (database == null)
{
new StoreDataAccess();
}
using (SQLiteConnection conn = new SQLiteConnection(path))
{
Items = storeDataAccess.StoreDetails;
StoreView.ItemsSource = Items;
}
}
}
}
'''
and lastly here is my databbase model for it:
'''
using System;
using System.Collections.Generic;
using System.Text;
using Xamarin.Forms;
using SQLite;
using System.ComponentModel;
namespace Project.DataClasses
{
class StoreDetails : INotifyPropertyChanged
{
private int _storeId;
[PrimaryKey, AutoIncrement, NotNull]
public int StoreId
{
get { return _storeId; }
set { _storeId = value; OnPropertyChanged(nameof(StoreId)); }
}
private string _storeName;
[NotNull, DefaultValue("Enter Store Name")]
public string StoreName
{
get { return _storeName; }
set { _storeName = value; OnPropertyChanged(nameof(_storeName)); }
}
private string _storeManger;
[NotNull, DefaultValue("Enter Store Managers Name")]
public string StoreManger
{
get { return _storeManger; }
set { _storeManger = value; OnPropertyChanged(nameof(StoreManger)); }
}
private string _storeNumber;
[NotNull, DefaultValue("Enter Store Number")]
public string StoreNumber
{
get { return _storeNumber; }
set { _storeNumber = value; OnPropertyChanged(nameof(StoreNumber)); }
}
private string _address;
[NotNull, DefaultValue("Enter Address")]
public string Address
{
get { return _address; }
set { _address = value; OnPropertyChanged(nameof(Address)); }
}
private int _merchandiserKey;
[NotNull]
public int MerchandiserKey
{
get { return _merchandiserKey; }
set { _merchandiserKey = value; OnPropertyChanged(nameof(MerchandiserKey)); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
'''
any help would be greatly appreciated
'''
public int SaveStoreDetails(StoreDetails storeDetailsInstance)
{
lock (collisionLock)
{
if (storeDetailsInstance.StoreId != 0)
{
database.Update(storeDetailsInstance);
return storeDetailsInstance.StoreId;
}
else
{
database.Insert(storeDetailsInstance);
return storeDetailsInstance.StoreId;
}
//database.Commit();
}
}
'''
this is the area where it all seems to be going wrong i just don't know why
Thank You Jason, you were correct in that the error was in calling both the savefunctions and overwriting it!!

How to access datagrid in View from ViewModel in Silverlight?

Hai i'm doing one silverlight app that uses MVVM architecture.
The Scenario is this. I have one combobox and datagrid in same page.
I have use ObservableCollection to bind the values in Datagrid and in that collection i have three fields namely Fname,Sname and Dept.
I bind Dept in Combobox but if i select any one of department means that value does not update in DataGrid. ie., i have created the code in ViewModel and i use LINQ query and i have Fetched the value also in,
var semp = from s in Employees where s.Dept.Equals(Names.Dept) select s;
i need to send this semp datasource to Datagrid in View.
Datagrid Syntax is :
<my:DataGrid x:Name="McDataGrid" ItemsSource="{Binding Employees,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" Margin="130,151,0,0" Height="137" VerticalAlignment="Top" RowBackground="#AA5D9324" AutoGenerateColumns="True" HorizontalAlignment="Left" Width="196">
</my:DataGrid>
Help me if u Know...
This is the ViewModel Code:
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using System.ComponentModel;
using Silverlight_MVVM.Model;
using Silverlight_MVVM.Utils;
using System.Linq;
using System.Collections.Generic;
namespace Silverlight_MVVM.ViewModel
{
public class EmployeeListViewModel:INotifyPropertyChanged
{
public ObservableCollection<Employee> Employees { get; private set; }
public EmployeeListViewModel()
{
Employees = Silverlight_MVVM.DataHelper.EmployeeDataHelper.EmployeeData ();
}
private string _fname;
public string Fname
{
get
{
return _fname;
}
set
{
_fname = value;
RaisePropertyChanged("Fname");
}
}
private string _sname;
public string Sname
{
get
{
return _sname;
}
set
{
_sname = value;
RaisePropertyChanged("Sname");
}
}
private string _dept;
public string Dept
{
get
{
return _dept;
}
set
{
_dept = value;
RaisePropertyChanged("Dept");
}
}
private Employee _SelectedEmployee;
public Employee SelectedEmployee
{
get
{
return _SelectedEmployee;
}
set
{
_SelectedEmployee = value;
RaisePropertyChanged("SelectedEmployee");
}
}
private string _demp;
public string demp
{
get
{
return _demp;
}
set
{
_demp = value;
RaisePropertyChanged("demp");
}
}
private Employee _Names;
public Employee Names
{
get
{
return _Names;
}
set
{
_Names = value;
List<Employee> myList = new List<Employee>();
IEnumerable<Employee> myEnumerable = myList;
// List<Employee> listAgain = myEnumerable.ToList();
// Employees = (ObservableCollection<Employee>)Employees.Where(_ => _.Dept.Equals(Names.Dept));
RaisePropertyChanged("Names");
}
}
public void HandleShowMessage()
{
// MessageBox.Show("Hello " + Names + ",Welcome to EventTrigger for MVVM.");
}
public RelayCommand _AddEmployeeCommand;
/// <summary>
/// Returns a command that show the customer.
/// </summary>
public ICommand AddEmployeeCommand
{
get
{
if (_AddEmployeeCommand == null)
{
_AddEmployeeCommand = new RelayCommand(
param => this.AddEmployee(),
param => this.CanAddEmployee
);
}
return _AddEmployeeCommand;
}
}
public bool CanAddEmployee
{
get
{
return true;
}
}
public void AddEmployee()
{
Employee newEmployee = new Employee();
if (Names == null)
{
newEmployee.Fname = this.Fname;
newEmployee.Sname = this.Sname;
newEmployee.Dept = this.Dept;
Employees.Add(newEmployee);
//SelectedEmployee = newEmployee.ToString();
}
else //This is the event for getting selected item through combobox and the linq query fetching
{
Employees = Silverlight_MVVM.DataHelper.EmployeeDataHelper.EmployeeData();
var semp = from emp in Employees where emp.Dept.Equals(Names.Dept) select emp;
}
}
#region INotifyPropertyChanged
// [field: NonSerialized]
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
}

Create a hierarchy custom server control

I have a self-referencing table and I want to visualize it using:
<ol>
<li>
</li>
</ol>
I want to create a custom server data-bound control with templates, I have read the MSDN article:
http://msdn.microsoft.com/en-us/library/aa479322.aspx
But I think that, I have to use different aproach and inherit the
HierarchicalDataBoundControl
or implement
IHierarchicalDataSource
But I cannot find any examples, or something to read from.
Can someone point me to a book or an article, or explain it to me in steps how it needs to be done.
A summary of what is required is this:
A Control which extends HierarchicalDataSourceControl AND DataSourceControl that implements IHeirarchicalDataSource. Believe me working from the documentation provided took A LOT of trial and error but in the end it is worth it. Mines been on hold but shortly I'll complete a project using this which will be able to bind to any n depth structure + navigate it in code using Node.GetParent().GetChildren().Where .. etc. It's complicted and may be overkill for what you need and you may revert back to repeater. Given the posting length allowed at stackoverflow I can't give you full code listing (some 100k chars)
To give you a flavour of whats in my other code here is the generic IHierachicalDataSourceControl:
#region Generic Hierachical DatasourceControl
/// <summary>
/// Datasource control
/// </summary>
public class GenericHierachicalDataSourceControl<TDataContext, TNode, TEntity> : HierarchicalDataSourceControl, IHierarchicalDataSource
where TDataContext : DataContext, new()
where TNode : class,PNS.GenericLinqNodeHeirachy<TDataContext, TNode, TEntity>.IHeirachicalNode, new()
where TEntity : class,PNS.GenericLinqNodeHeirachy<TDataContext, TNode, TEntity>.IHeirachyNodeEntity, new()
{
NodeDataSourceView view;
protected override HierarchicalDataSourceView GetHierarchicalView(string viewPath)
{
view = new NodeDataSourceView(viewPath);
return view;
}
public class NodeDataSourceView : HierarchicalDataSourceView
{
private string _viewPath;
public NodeDataSourceView(string viewPath)
{
_viewPath = viewPath;
}
public override IHierarchicalEnumerable Select()
{
var hierarchy = new HierarchicalEnumerable();
List<TNode> topNodes;
if (String.IsNullOrEmpty(_viewPath))
{
//get all top level nodes (ones without parents)
topNodes = GenericLinqNodeHeirachy<TDataContext, TNode, TEntity>.NodesDAL.GetTopLevelNodes().ToList();
}
else
{
//get the last node in the path
string[] nodes = _viewPath.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
topNodes = new List<TNode>();
topNodes.Add(GenericLinqNodeHeirachy<TDataContext, TNode, TEntity>.NodesDAL.GetNode(nodes[nodes.Length - 1]));
}
//for each node in the path
foreach (var node in topNodes)
{
if (node.Entity != null)
{
hierarchy.Add(node.Entity);
}
}
return hierarchy;
}
}
public class HierarchicalEnumerable : List<TEntity>, IHierarchicalEnumerable
{
public HierarchicalEnumerable()
: base()
{
}
public IHierarchyData GetHierarchyData(object enumeratedItem)
{
return enumeratedItem as IHierarchyData;
}
}
}
and another part:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI.WebControls;
using System.Web.UI;
using System.Web.UI.HtmlControls;
namespace BootstrapProject.CodeBase
{
public class GenericHierarchicalDataboundControl : HierarchicalDataBoundControl
{
private string _textField;
public string TextField
{
get { return _textField; }
set { _textField = value; }
}
protected override string TagName
{
get
{
return "div";
}
}
protected override HtmlTextWriterTag TagKey
{
get
{
return HtmlTextWriterTag.Div;
}
}
protected override void CreateChildControls()
{
if (null != Page && Page.IsPostBack && null != ViewState["_!DataBound"])
{
this.RequiresDataBinding = true;
this.EnsureDataBound();
}
}
protected override void PerformDataBinding()
{
IHierarchicalEnumerable dataSource = GetData(string.Empty).Select();
this.PerformDataBinding(0, this.Controls, dataSource);
this.MarkAsDataBound();
}
protected virtual void PerformDataBinding(int level, ControlCollection controls, IHierarchicalEnumerable dataSource)
{
if (null != dataSource)
{
//controls.Clear();
HtmlGenericControl ul = new HtmlGenericControl("ul");
foreach (object value in dataSource)
{
var itemData = dataSource.GetHierarchyData(value);
Control item = CreateAndBindControl(level, value);
ul.Controls.Add(item);
var data = dataSource.GetHierarchyData(value);
if (data != null && data.HasChildren)
{
IHierarchicalEnumerable childData = data.GetChildren();
PerformDataBinding(1 + level, item.Controls, childData);
}
controls.Add(ul);
}
}
}
protected virtual Control CreateAndBindControl(int level, object dataItem)
{
HtmlGenericControl li = new HtmlGenericControl("li");
string text = String.Empty;
if (!String.IsNullOrEmpty(TextField))
{
text = DataBinder.GetPropertyValue(dataItem, TextField).ToString();
}
else
{
text = dataItem.ToString();
}
li.Attributes.Add("rel", text);
li.Controls.Add(new HyperLink { Text = text });
return li;
}
}
}
And finally:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using BootstrapProject.CodeBase.DAL;
using PNS;
namespace BootstrapProject.CodeBase
{
public class NodeDataSourceControl : HierarchicalDataSourceControl, IHierarchicalDataSource
{
NodeDataSourceView view;
protected override HierarchicalDataSourceView GetHierarchicalView(string viewPath)
{
view = new NodeDataSourceView(viewPath);
return view;
}
}
public class NodeDataSourceView : HierarchicalDataSourceView
{
private string _viewPath;
public NodeDataSourceView(string viewPath)
{
_viewPath = viewPath;
}
public override IHierarchicalEnumerable Select()
{
var hierarchy = new CMSPageHierarchicalEnumerable();
List<DAL.Node> topNodes;
if (String.IsNullOrEmpty(_viewPath))
{
//get all top level nodes (ones without parents)
topNodes = CMS.NodesDAL.GetTopLevelNodes().ToList();
}
else
{
//get the last node in the path
string[] nodes = _viewPath.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
topNodes = new List<DAL.Node>();
topNodes.AddRange(CMS.NodesDAL.GetNode(nodes[nodes.Length - 1]).NodeChildren);
}
//for each node in the path
foreach (var node in topNodes)
{
if (node.Page != null)
{
hierarchy.Add(node.Page);
}
}
return hierarchy;
}
}
}

multiple IStateManager in StateManagedCollection

I was reading a post at VS 2008, ASP.NET: Generate Local Resources.
Mehdi Golchin showed us a beautiful job of StateManagedCollection.
However I was wondered about using multiple classes of IStateManager in one StateManagedCollection.
As you can see below:
public class MenuItemCollection : StateManagedCollection
{
public MenuItem this[int index]
{
get { return (MenuItem)((IList)this)[index]; }
}
public int Add(MenuItem item)
{
return ((IList)this).Add(item);
}
public void Remove(MenuItem item)
{
((IList)this).Remove(item);
}
// Write Insert and RemoveAt methods
protected override void SetDirtyObject(object o)
{
((MenuItem)o).SetDirty();
}
}
This MenuItemCollection class can have only one child class("MenuItem").
If I want to use another class as well as MenuItem class, for example MenuItem2 class, how do I have to write the codes?
Anyone can help me?
Thanks in advance.
Write a generic version - for example,
public class GenericStateManagedCollection<T> : StateManagedCollection
where T: IStateManager, new()
{
public T this[int index]
{
get { return (T)((IList)this)[index]; }
}
public int Add(T item)
{
return ((IList)this).Add(item);
}
public void Remove(T item)
{
((IList)this).Remove(item);
}
// Write Insert and RemoveAt methods
protected override void SetDirtyObject(object o)
{
((T)o).SetDirty();
}
protected override object CreateKnownType(int index)
{
return Activator.CreateInstance<T>();
}
protected override Type[] GetKnownTypes()
{
return new Type[] { typeof(T) };
}
}
And use it as
public class MenuItemCollection : GenericStateManagedCollection<MenuItem> { }
public class XyzItemCollection : GenericStateManagedCollection<XyzItem> { }
EDIT:
I have most probably mis-understood your question! Assuming now that you want to put two different type of objects into the StateManagedCollection. From usage perspective, it doesn't make sense to have objects of completely unrelated types into the collection - you need to have some base class. For example, consider DataControlFieldCollection which holds instances of (abstract) type 'DataControField. BoundField, ButtonField etc inherits fromDataControField`.
So you need to go via similar route - for example,
public class MenuItemBase : IStateManager
{
// Use implementation from link you quoted (Mehdi Golchin's answer)
...
}
public class MenuItem : MenuItemBase
{
...
}
public class MenuItem2 : MenuItemBase
{
...
}
public class MenuItemCollection : StateManagedCollection
{
public MenuItemBase this[int index]
{
get { return (MenuItemBase)((IList)this)[index]; }
}
public int Add(MenuItemBaseitem)
{
return ((IList)this).Add(item);
}
public void Remove(MenuItemBaseitem)
{
((IList)this).Remove(item);
}
// Write Insert and RemoveAt methods
protected override void SetDirtyObject(object o)
{
((MenuItemBase)o).SetDirty();
}
// important to override CreateKnownType and GetKnownTypes
private static readonly Type[] _knownTypes = new Type[] {typeof(MenuItem), typeof(MenuItem2) }
protected override Type[] GetKnownTypes()
{
return _knownTypes;
}
protected override object CreateKnownType(int index)
{
switch (index)
{
case 0:
return new MenuItem();
case 1:
return new MenuItem2();
default:
throw new Exception("Invalid Index");
}
}
}
Note: Untested code

how do I map an asp.net user control property to a server control within it?

I have a user control with a WebDateTimeEdit server control on it (essentially a TextBox). I'd like to be able to set some of the server control's properties by way of the user control's markup or programatically. for example I have this defined on my user control:
public string CssClass
{
get { return this.WebDateTimeEdit1.CssClass; }
set { this.WebDateTimeEdit1.CssClass = value; }
}
which allows me to do
<uc1:MyControl ID="MyControl1" runat="server" CssClass="fancycss" />
and this works. but if I want to add a control through code,
MyControl myControl2 = new MyControl();
MyControl.CssClass = "fancycss";
this blows up because WebDateTimeEdit1 is null.
is there any way I can make this happen? also can do I do this
myControl2 .Font.Size = FontUnit.Point(8);
where the Font property is read only on the server control?
It depends on how your control is defined (is it a CompositeControl?), But generally speaking, you want to call EnsureChildControls() as the first line of the setter (and likely the getter too)
The issue you are facing is due to the fact that web controls by nature are stateless. You need to persist the value of the properties you are setting so they are accessable between postbacks. Below is an example that implements asp.net viewstate.
So for example to enable state and avoid the null condition you are experienceing with the CssClass property of your custom control you can implement the propery as follows.
private string CssClass
{
get
{
return (string)ViewState["cssclass"];
}
set
{
ViewState["cssclass"] = value;
}
}
I have included a sample user control I wrote recently that will give you a model to work from.
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.ComponentModel;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
namespace Pdc.EventPro.WebControls
{
[DefaultProperty("Text"), ToolboxData("<{0}:AnchorDomain1 runat=server></{0}:AnchorDomain1>")]
public class AnchorDomain : Control
{
private string _href = string.Empty;
public AnchorDomain()
{
VirtualPath = HttpContext.Current.Request.Path.Substring(0, HttpContext.Current.Request.Path.LastIndexOf("/") + 1);
}
private string VirtualPath
{
get
{
return (string)ViewState["virtualPath"];
}
set
{
ViewState["virtualPath"] = value;
}
}
[Bindable(true), Category("Content"), DefaultValue("Performance Development Corporation")]
public string Title
{
get
{
return (string)ViewState["title"];
}
set
{
ViewState["title"] = value;
}
}
[Bindable(true), Category("Content"), DefaultValue("")]
public string LinkText
{
get
{
return (string)ViewState["linktext"];
}
set
{
ViewState["linktext"] = value;
}
}
[Bindable(true), Category("Content"), DefaultValue("")]
public string Url
{
get
{
return (string)ViewState["url"];
}
set
{
ViewState["url"] = value;
}
}
[Bindable(true), Category("Content"), DefaultValue("false")]
public bool UsePageVirtualPath
{
get
{
return (bool)ViewState["useVirtualPath"];
}
set
{
ViewState["useVirtualPath"] = value;
}
}
[Bindable(true), Category("Content"), DefaultValue("false")]
public string CssClass
{
get
{
return (string)ViewState["CssClass"];
}
set
{
ViewState["CssClass"] = value;
}
}
protected override void Render(HtmlTextWriter writer)
{
if (string.IsNullOrEmpty(Url) && UsePageVirtualPath == false)
{
_href = CreateUri(HttpContext.Current.Request.Url.GetLeftPart(System.UriPartial.Authority), HttpContext.Current.Request.ApplicationPath).ToString();
}
else if (!string.IsNullOrEmpty(Url) && UsePageVirtualPath == true)
{
_href = CreateUri(HttpContext.Current.Request.Url.GetLeftPart(System.UriPartial.Authority), CombineUri(VirtualPath, Url)).ToString();
}
else
{
_href = CreateUri(HttpContext.Current.Request.Url.GetLeftPart(System.UriPartial.Authority), CombineUri(HttpContext.Current.Request.ApplicationPath, Url)).ToString();
}
writer.WriteBeginTag("a");
writer.WriteAttribute("href", _href);
writer.WriteAttribute("title", Title);
writer.WriteAttribute("class", CssClass);
writer.Write(HtmlTextWriter.TagRightChar);
writer.Write(LinkText);
writer.WriteEndTag("a");
base.Render(writer);
}
private Uri CreateUri(string baseUri, string relativeUri)
{
Uri result = null;
if (Uri.TryCreate(new Uri(baseUri), relativeUri, out result))
{
return result;
}
return result;
}
private string CombineUri(string basePath1, string basePath2)
{
return string.Format("{0}/{1}", basePath1.TrimEnd('/'), basePath2.TrimStart('/'));
}
}
}
Enjoy!

Resources