May 24, 2010, 2:35 PM
Master/Detail and reusable content
Hello,
I'm trying to develop a litle framework based on ext.net.
<ul>[*]I've a MasterPage that is inherited for registers. Each subject has its inheritance.[*]Inside this MasterPage there is a UserControl used for Search wich its
grid columns and filter fields are built dynamically;[/list]
<body>
<form id="form1" runat="server">
<ext:ResourceManager ID="ResourceManager1" runat="server" ScriptMode="Release"/>
<ext:Panel ID="ToolbarsPanel" runat="server" Border="false" BodyStyle="padding:10px;" Layout="Fit">
<TopBar>
<ext:Toolbar ID="TopBar" runat="server">
<Items>
<ext:Button ID="btnFind" runat="server" Text="Pesquisar" Icon="Find">
<DirectEvents>
<Click OnEvent="btnFind_Click">
<EventMask ShowMask="true" Msg="Aguarde..." />
</Click>
</DirectEvents>
</ext:Button>
<ext:Button ID="btnSave" runat="server" Text="Salvar" Icon="Disk">
<DirectEvents>
<Click OnEvent="btnSave_Click" ViewStateMode="Enabled">
<EventMask ShowMask="true" Msg="Aguarde..." />
</Click>
</DirectEvents>
</ext:Button>
</Items>
</ext:Toolbar>
</TopBar>
<Content>
<asp:ContentPlaceHolder ID="cph" runat="server">
</asp:ContentPlaceHolder>
</Content>
</ext:Panel>
<ucl:Search ID="ucSearch" runat="server"/>
</form>
</body>
CodeBehind [DirectMethodProxyID(IDMode = DirectMethodProxyIDMode.None)]
public partial class MasterCadastro : System.Web.UI.MasterPage
{
public event DirectEvent.DirectEventHandler Search;
public event DirectEvent.DirectEventHandler Save;
protected void btnFind_Click(object sender, DirectEventArgs e)
{
Search(sender, e);
}
protected void btnSave_Click(object sender, DirectEventArgs e)
{
Save(sender, e);
}
public UCSearchUserControl SearchControl
{
get
{
return this.ucSearch;
}
}
}
UCSearch UserControl:<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="UCSearchUserControl.ascx.cs" Inherits="Shared.Search.UCSearchUserControl" %>
<%@ Register assembly="Ext.Net" namespace="Ext.Net" tagprefix="ext" %>
<ext:Window
ID="winSearch"
runat="server"
Icon="Find"
Title="Pesquisar"
Resizable="false"
Hidden="true"
AutoShow="false"
Plain="true"
Modal="true"
Width="700"
Height="500">
<Items>
<ext:BorderLayout runat="server">
<North>
<ext:Panel ID="pnlBody" runat="server" LabelAlign="Top" Layout="Form" Border="false" Padding="5" AutoHeight="true">
</ext:Panel>
</North>
<Center>
<ext:GridPanel ID="gridPanel" runat="server"
Border="false"
TrackMouseOver="true">
<Store>
<ext:Store ID="searchStore" runat="server" IgnoreExtraFields="false">
<Reader>
<ext:JsonReader>
</ext:JsonReader>
</Reader>
</ext:Store>
</Store>
<SelectionModel>
<ext:RowSelectionModel runat="server"/>
</SelectionModel>
<ColumnModel ID="cmGridPanel" runat="server">
<Columns>
</Columns>
</ColumnModel>
<DirectEvents>
<RowDblClick OnEvent="OnRowDblClick" ViewStateMode="Enabled">
<ExtraParams>
<ext:Parameter Name="data" Mode="Raw" Encode="true" Value="this.selModel.selections.items[0].data" />
</ExtraParams>
</RowDblClick>
</DirectEvents>
<BottomBar>
<ext:PagingToolbar ID="pagingTool" runat="server" PageSize="13" HideRefresh="true" AutoShow="true"/>
</BottomBar>
</ext:GridPanel>
</Center>
</ext:BorderLayout>
</Items>
<Buttons>
<ext:Button runat="server" ID="btnPesquisar" Text="Pesquisar" Icon="Find" OnDirectClick="btnPesquisa_Click">
<DirectEvents>
<Click OnEvent="btnPesquisa_Click">
<EventMask CustomTarget="#{gridPanel}" ShowMask="true" />
</Click>
</DirectEvents>
</ext:Button>
<ext:Button runat="server" ID="btnSelecionar" Text="Selecionar" Icon="Accept">
<DirectEvents>
<Click OnEvent="OnRowDblClick" ViewStateMode="Enabled">
<ExtraParams>
<ext:Parameter Name="data" Mode="Raw" Encode="true" Value="#{gridPanel}.selModel.selections.items[0].data" />
</ExtraParams>
</Click>
</DirectEvents>
</ext:Button>
</Buttons>
</ext:Window>
UCSearch CodeBehind: public partial class UCSearchUserControl : UserControl
{
public event ReturnSearchEventHandler ReturnSearch;
protected void Page_Load(object sender, EventArgs e)
{
}
public void Show(Control animateTarget)
{
winSearch.Show(animateTarget);
}
protected void OnRowDblClick(object sender, DirectEventArgs e)
{
SearchParams searchParams = SearchBase.GetSearch(this.Context); // From Session
ReturnSearchEventArgs args = new ReturnSearchEventArgs();
args.Data = JSON.Deserialize(e.ExtraParams["data"], searchParams.ReturnSearchType);
args.CallerID = searchParams.CallerID;
winSearch.Hide();
SearchBase.RemoveSearch(this.Context); // From Session
ReturnSearch(sender, args);
}
public SearchParams Config
{
set
{
searchStore.RemoveFields();
winSearch.Title = value.Title;
PropertyInfo[] returnPropInfo;
returnPropInfo = value.ReturnSearchType.GetProperties(BindingFlags.Instance | BindingFlags.Public);
for (int i = 0; i < returnPropInfo.Length; i++)
{
searchStore.AddField(new RecordField(returnPropInfo[i].Name));
}
// Add form fields
pnlBody.RemoveAll();
foreach (SearchParam param in value.Params)
{
if (param.SearchComponent != null)
{
param.SearchComponent.ID = string.Format("{0}_{1}", pnlBody.ClientID, param.SearchComponent.ID);
param.SearchComponent.AddTo(pnlBody);
}
}
pnlBody.UpdateContent();
ColumnModel cm = gridPanel.ColumnModel;
// add grid columns
cm.Columns.Clear();
cm.Columns.AddRange(value.Columns);
pagingTool.SetPageIndex(1);
gridPanel.Reconfigure();
SearchBase.SetSearch(this.Context, value); // Into Session
}
}
public void btnPesquisa_Click(object sender, DirectEventArgs e)
{
SearchParams searchParams = SearchBase.GetSearch(this.Context); // From Session
DataAccessManager dam = DataAccessManager.GetDefaultDataAccessManager(this.Context);
IDataAccess da = dam.CreateDataAccessObject();
try
{
List<DataAccessParameter> parameters = new List<DataAccessParameter>();
foreach (SearchParam param in searchParams.Params)
{
object valor = null;
if (param.HiddenValue != null)
{
valor = param.HiddenValue;
}
else
{
if (this.Request[param.SearchComponent.ID + "_value"] != null)
{
valor = this.Request[param.SearchComponent.ID + "_value"];
}
else
{
valor = this.Request[param.SearchComponent.ID];
}
}
parameters.Add(new DataAccessParameter(param.ParamName, param.DBType,
Util.DataConvert.ToDatabase(valor)));
}
da.OpenConnection();
DataTable dataTable = new DataTable();
da.FillDataTable(searchParams.CommandText, searchParams.CommandType, parameters, dataTable);
pagingTool.SetPageIndex(1);
gridPanel.Store.Primary.DataSource = dataTable;
gridPanel.Store.Primary.DataBind();
}
finally
{
if (da != null)
{
da.CloseConnection();
da.Dispose();
}
}
}
}
Parameter for create searchs public class SearchParams
{
public SearchParams()
{
Params = new List<SearchParam>();
Columns = new ColumnCollection();
}
public MethodInfo ReturnSearchInfo { get; set; }
public String CallerID { get; set; }
public Type ReturnSearchType;
public Int16 BodyHeight { get; set; }
public String Title { get; set; }
public String CommandText { get; set; }
public CommandType CommandType { get; set; }
public List<SearchParam> Params { get; set; }
public ColumnCollection Columns { get; set; }
}
public class SearchParam
{
public SearchParam()
{
}
private object hiddenValue;
public object HiddenValue
{
get { return hiddenValue; }
set
{
if (searchComponent != null)
{
throw new Exception("It is not possible set 'HiddenValue' and 'SearchComponent' at the same parameter!");
}
hiddenValue = value;
}
}
private Field searchComponent;
public Field SearchComponent
{
get { return searchComponent; }
set
{
if (searchComponent != null)
{
throw new Exception("It is not possible set 'HiddenValue' and 'SearchComponent' at the same
parameter!");
}
searchComponent = value;
}
}
public String ParamName { get; set; }
public DbType DBType { get; set ; }
}
Here is the final user interface:
<asp:Content ID="Content2" ContentPlaceHolderID="cph" runat="server">
<ext:Store runat="server" IgnoreExtraFields="false" ID="storePrinciple" EnableViewState="true">
<Reader>
<ext:JsonReader IDProperty="idPrinciple">
<Fields>
<ext:RecordField Name="idPrinciple" Type="Int"/>
<ext:RecordField Name="dsPrinciple" />
</Fields>
</ext:JsonReader>
</Reader>
</ext:Store>
<ext:Panel ID="pnlForm" runat="server" LabelAlign="Top" Layout="Form" Border="false">
<Items>
<ext:NumberField ID="nrIdConcept" runat="server" FieldLabel="ID" Width="80" MaxLength="6" Disabled="true"/>
<ext:TextField ID="txtNmConcept" runat="server" FieldLabel="Name" Width="270"/>
<ext:GridPanel ID="gdrPrinciple" runat="server" Frame="true" StoreID="storePrinciple"
Title="Principle" AutoHeight="true" Width="560">
<ColumnModel ID="clmnMdlPrinciple" runat="server">
<Columns>
<ext:Column ColumnID="clIdPrinciple" DataIndex="idPrinciple" Header="ID" Width="80" Align="Center"/>
<ext:Column DataIndex="dsPrinciple" Header="Name" Width="370" />
</Columns>
</ColumnModel>
<SelectionModel>
<ext:RowSelectionModel runat="server" SingleSelect="true"/>
</SelectionModel>
<Plugins>
<ext:GridPanelMaintainScrollPositionOnRefresh runat="server" />
</Plugins>
<BottomBar>
<ext:Toolbar ID="Toolbar1" runat="server">
<Items>
<ext:Button ID="btnInsertPrinciple" Text="Adicionar" Icon="Add" runat="server">
<DirectEvents>
<Click OnEvent="btnInsertPrinciple_Click">
<EventMask ShowMask="true" CustomTarget="#{gdrPrinciple}" />
</Click>
</DirectEvents>
</ext:Button>
</Items>
</ext:Toolbar>
</BottomBar>
</ext:GridPanel>
</Items>
</ext:Panel>
</asp:Content>
protected void Page_Load(object sender, EventArgs e)
{
master = (MasterCadastro)Master;
master.Search += new ComponentDirectEvent.DirectEventHandler(OnSearch);
master.Save += new ComponentDirectEvent.DirectEventHandler(OnSave);
master.SearchControl.ReturnSearch += new ReturnSearchEventHandler(OnReturnSearch);
}
public void OnReturnSearch(Object sender, ReturnSearchEventArgs e)
{
if (e.CallerID == master.ID)
{
BVConcept retornoPesquisa = (BVConcept)e.Data;
nrIdConcept.Text = retornoPesquisa.id_concept.ToString();
txtNmConcept.Text = retornoPesquisa.ds_concept.ToString();
}
else if (e.CallerID == btnInsertPrinciple.ID)
{
BVPrinciple retornoPesquisa = (BVPrinciple )e.Data;
/*
BEFORE I INSERT THE RECORD ON STORE I NEED TO VALIDATE IT IS ALREADY INSERTED.
HOW CAN I GET THE STORE DATA HERE TO VALIDADE DUPLICATED IDS INTO THE STORE?
*/
storePrinciple.AddRecord(retornoPesquisa);
}
}
public void btnInsertPrinciple_Click(object sender, DirectEventArgs e)
{
SearchPrinciple.Search(Context, master.SearchControl, sender, btnInsertPrinciple.ID);
}
public void OnSearch(object sender, DirectEventArgs e)
{
SearchConcept.Search(Context, master.SearchControl, sender, master.ID);
}
public void OnSave(object sender, Ext.Net.DirectEventArgs e)
{
BVConcept valueConcept; // Master / Detail
try
{
valueConcept= new BVConcept ();
valueConcept.idVacinaMedicamento = Util.DataConvert.ToInt(nrIdConcept.Text);
valueConcept.nmVacinaMedicamento = txtNmConcept.Text;
/*
valueConcept.Principles List<BVPrinciple>
HOW CAN I GET PRINCIPLE'S STORE HERE? THIS EVENT IS THROWNBY A MASTER PAGE.
*/
ControllerConcept.Save(valueConcept);
}
finally
{
valueConcept= null;
}
}