Hur fungerar egentligen __doPostback Använd Page.GetPostBackReference() funktionen, den ger dig den script-kod som behövs för att __doPostback ska kunna anropas med rätt parametrar. Titta i sdk:n så hittar du mer information om den GetPostBackEventReference hette den visst ;) När iaf. :) får verkligen inte rätt på det, alla exempel som jag testar funkar inte. ok. Jag vill ha med ett Item till min Event också. Hur får jag med ett Item när man onclick körs Jag har sett att i vb.net så kan man skriva så här typ Om du har en Treeview (har du byggt den själv?) Så förmodar jag att den redan har ett event vid klick av en nod. Om du byggt den själv varför inte gära alla noder till en LinkButton eller liknande? Då kan du styra allt själv, genom att trigga eget event vid Click för LinkButton där du skickar dina egna argument. Jag håller på att bygga en Toolbar control och lägger in ToolbarItems i en ToolbarItemCollection sen så loopas dessa ut. Jag kör en event när man klickar på en <TD> Du är på rätt väg. Jag gjorde så här Nu kommer du in på lite svårare områden :-) Okej det börjar bli lite svåare, det märker jag... Finns bättre o mer fungerande sätt att göra på. Kan du hjälpa mig lite på vägen, eller har du någon länk till något sida där de gör liknande. Hej, Så, har nu skrivit en artikel om detta med Staten. Oj detta var inte dåligt. Nu ska jag läsa denna och försöka förstå. Kanon artikel, verkligen jättebra Trevligt, men vad tusan försöker du säger i början av artikeln ? Hej, Gessle.. :) detta är riktigt roligt, tänker på hur många olika användbara kontroller man kan bygga när man lärt sig detta. Är väldigt inspirerad att lära mig mer om detta. Men antagligen så har jag lite bråttom nu och får inte rätt på det. "ska denna vara virtual? Vad menas med det?" Okej har testat en del saker, och börjar nog komma närmare problemet. Detta kan väl inte bli rätt...eller Hej, Stämmer verkligen koden eller är det jag som är helt snurrig. Förlåt. Hej, Hejsan __dopostback
kan jag göra så att en <td> går in i en event i codebehind.
om jag har en <TD>
hur ska jag göra för att en event ska köras när jag klickar på den
function test(object)
{
__doPostBack(object,'');
}
</script>
<TD id="a1" style="WIDTH: 64px" onclick="test(this)" runat="server">
förstår inte riktigt hur jag ska göra för att komma in i codebehind?Sv: __dopostback
Sv: __dopostback
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemwebuipageclassgetpostbackeventreferencetopic.asp
Alt.
GetPostBackClientEvent:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemwebuipageclassgetpostbackeventreferencetopic2.asp
Jag har inte en aning om vad som är skillnad, om det nu är någon skillnad dvs. De har samma (den ena har två varianter) parametrar och båda har samma beskrivning. Jag vet inte vad jag själv har använt ;) Fast jag tror det var den första då det var den enda jag kom ihåg i huvudet :)Sv: __dopostback
Någon som kan visa ett jätteenkelt exempel som fungerar.Sv: __dopostback
Först så har du Page.GetPostBackEventRefference(control,value)
när du skapar denna så kommer den ge dig en sträng som ser ut typ så här:
__doPostBack('<controllesn unika id >','1'
sedan kommer ett JavaScript att läggas in på sidan. (klistrar inte in det här.)
den kontroll som du skickar in i meotden GetPostBackEventRefference är den kontrol som du sedan måste ha metoden RaisePostBackEvent(string argument) på. Du måst even på denna kontroll ärva
Interface IPostBackEventHandler
För att få detta script att fungera måste du själv trigga det.
Låt säga en tr.
<tr onclick="JavaScript:" + Page.GetPostBackEventRefference(control,value) +"">;
Som då kan ge.
<tr onclick="JavaScript:__doPostBack('<controllesn unika id >','1'">
När du tryker på denna kommer din RaisePostBackEvent på den kontrollen du angav att triggas.
Mvh JohanSv: __dopostback
<code>
public event EventHandler Click;
protected virtual void OnClick(EventArgs e)
{
if (Click != null)
{
Click(this, e);
}
}
public void RaisePostBackEvent(string eventArgument)
{
//kan kanske ha ett ID med som jag sen tar ut rätt Item i en Collection
// men hur skickar jag sen med det rätta till onclick
OnClick(new EventArgs());
}
public string GetPostBackClientEvent(string EventArgs)
{
return Page.GetPostBackClientEvent(this, EventArgs);
}
//så här ser det ut i min codebehind
private void ToolBar_Click(object sender, System.EventArgs e)
{
}
</code>Sv: __dopostback
Public Event OnNodeLoadOnDemand(ByRef Item As MyTreeViewItem)Sv: __dopostback
Mvh JohanSv: __dopostback
tc.Attributes.Add("onClick", Toolbar.GetPostBackClientEvent("c1"));
När jag klickar på <TD> går jag in här
<code>
public void RaisePostBackEvent(string eventArgument)
{
OnClick(new EventArgs());
}
</code>
Nu har jag med mitt ToolbarItems ID, jag kan nu leta upp rätt Item och på något sätt skicka med det till min codebehind.
så här gör exemplet jag har i vb.net i codebehind
<code>
private void MyTreeView1_OnNodeLoadOnDemand(ref MyTreeViewItem Item)
{
}
Är jag ute och snurrar eller finns det något hopp att få rätt på dettaSv: __dopostback
Plocka ID som kanske är index på rad eller nått, plocka sedan ut det Item du har i din collection baserat på ID. Skicka med det i en egen EventArgsklass som en property.
public class ItemEventArgs : EventArgs
{
public Item... _item;
public Item... Item
{
get{return this._item; }
set{ this._item = value; }
}
}
Sedan bygger du ett eget Delagat, och Event där du har med denna som parameter.
I din RaisedPostBack... skapar du en ItemEventArgs sätter Item till ditt Item och sedan skivkar in
det i den metod som din app lyssnar på. I din Codebehind kan du sedan skapa upp eventlyssnaren,
metoden som skall anropas och få ut Item från ditt egna EventArgs.
Hängde du med?
Mvh JohanSv: __dopostback
* skapade upp en ny eventarg klass
* i min RaisePostBackEvent
<code>
public delegate void MyClickDelegate(ItemEventArgs e);
public event MyClickDelegate Click;
public void RaisePostBackEvent(string eventArgument)
{
myOPTOToolbarItem myItem = Items.GetItem(eventArgument);
ItemEventArgs myItemEventArgs = new ItemEventArgs();
iea.Item = myItem;
OnClick(myItemEventArgs);
}
protected virtual void OnClick(ItemEventArgs e)
{
Click(e);
}
</code>
Kanon, detta var jättebra att jag löste detta.
Har ett annat problem också och det är att min itemcollection inte sparas, utan försvinner hela tiden
Hur ska jag göra för att ha den i minnet.
Ska man på något sätt spara ner den i viewstate eller?
Så här ser min ToolbarCollection ut. använder add för att lägga till nya Item i List.
Men hur ska jag sen kunna spara de osv...
<code>
public class MyToolbarCollection : CollectionBase
{
public MyToolbarCollection() :base()
{
}
public void Add(myToolbarItem Item)
{
List.Add(Item);
}
}
</code>Sv: __dopostback
Du kan om du vill spara den i en session (ful lösning) men effektiv o kräver inte en massa utvtid.
Har du all tid i världen är Viewstate ett bra val. Dock måste du nyttja Statebag i dina Items där du
för varje Item sparar ditt värde i StateBagen (vid set) och hämtar ur viewStaten (vid Get).
Du måste även hantera Load resp SaveViewstate för dina Item.
Därefter måste din Collection oxå ha Load och SaveViewstate implementerat där du i Save ittererar genom alla dina Items o ropar på dess SaveViewState och vid Load ittererar och kör alla Items LoadViewstate.
Typ så. I korta drag.
Mvh JohanSv: __dopostback
Jag såg ett exempel som gjorde typ såhär. Men jag får fel. (TypConverter eller serilizable)
verkar inte gå att lägga in min collection i veiwstaten.
<code>
protected override void LoadViewState(object savedState)
{
if (savedState != null)
{
object[] State = (object[])savedState;
this.Value = (string) State[0];
MyToolbarCollection ItemsList = (MyToolbarCollection)State[1];
foreach (myToolbarItem Item in ItemsList)
{
Items.Add(Item);
}
}
}
protected override object SaveViewState()
{
MyToolbarCollection ItemsList = new MyToolbarCollection();
foreach (myToolbarItem item in this.Items)
{
ItemsList.Add(item);
}
object[] savedState = new object[2];
savedState[0] = this.Value;
savedState[1] = ItemsList;
return savedState;
}
</code>Sv: __dopostback
Men dock kräver det mer text och förklaringar vilket jag inte har tid med just nu :-(
Det är lite trixigt att få till det du vill göra på ett bra sätt.
Mvh JohanSv: __dopostback
Jag förstår inte riktigt hur jag ska gå vidare nu.
Här är min CollectionClass
Frågor.
Ska jag ha LoadViewState och SaveviewState här?
Är min add metod rätt. Är det smart att använda List?
<code>
public class ToolBarItemCollection : CollectionBase
{
public ToolBarItemCollection()
{
}
public void add(ToolBarItem Item)
{
List.Add(Item);
}
public void Render(System.Web.UI.WebControls.WebControl Owner,ToolBar tb,TableRow tr)
{
foreach(ToolBarItem Item in tb.Items)
{
Item.Render(Owner,tr);
}
}
}</code>
Här är min Item
Frågor. Hur ska jag göra i Load och save viewstate här?
<code>
public class ToolBarItem
{
private string _Text;
public ToolBarItem()
{
}
protected override void LoadViewState(object savedState)
{
if (savedState != null)
base.LoadViewState(savedState);
}
protected override object SaveViewState()
{
return base.SaveViewState();
}
public void Render(System.Web.UI.WebControls.WebControl Owner,TableRow tr)
{
TableCell tc = new TableCell();
Label l = new Label();
l.Text = this.Text;
tc.Controls.Add(l);
tc.Attributes.Add("onClick", "alert('" + this.Text + "')");
tr.Controls.Add(tc);
}
public string Text
{
get{return _Text;}
set{_Text = value;}
}
}
</code>
Här är min myToolbar class
Frågor. Ska jag ha denna raden med här
public MyToolbarCollection _Items = new MyToolbarCollection();
<code>
public class ToolBar : System.Web.UI.WebControls.WebControl
{
public ToolBarItemCollection _Items = new ToolBarItemCollection();
public ToolBarItemCollection Items
{
get{return _Items;}
}
protected override void RenderContents(HtmlTextWriter writer)
{
Table df = new Table();
df.Attributes.Add("Class","N");
df.ID = "HMTB";
df.CellSpacing = 0;
df.CellPadding = 0;
df.Attributes.Add("Border","0");
TableRow tr1 = new TableRow();
TableCell tc1 = new TableCell();
TableRow tr2 = new TableRow();
TableCell tc2 = new TableCell();
tc1.ColumnSpan = 2;
Label l = new Label();
l.Text = "|";
tc2.Controls.Add(l);
TableRow tr3 = new TableRow();
tr1.Controls.Add(tc1);
tr2.Controls.Add(tc2);
df.Controls.Add(tr1);
Panel RenderPanel = new Panel();
RenderPanel.Attributes.Add("style","cursor:hand");
Items.Render(RenderPanel,this,tr2);
df.Controls.Add(tr2);
RenderPanel.Controls.Add(df);
RenderPanel.RenderControl(writer);
}
}
</code>
mycket kod men det kanske hjälper till att hjälpa migSv: __dopostback
Har brådis nu.
Men kolla på StateBag så ser du hur du använder den. Så får du lite hjälp på vägen.
Skrev även hur du skulle göra i stora drag i något inlägg ovan. Läs det igen efter du kollat int
StateBag.
Som sagt det är lite klurigt och jut nu hinner jag inte :-( mkt att stå i...
Får ta det senare i så fall.
Mvh JohanSv: __dopostback
Hoppas jag fick med allt.
http://www.pellesoft.se/communicate/forum/view.aspx?msgid=150594&forumid=10&sum=1
Mvh JohanSv: __dopostback
Tack så jättemycketSv: __dopostback
Jag försökte implementera din lösning på min toolbar och allt verkade gå perfekt.
Jag kunde nu lägga till Item i designläget och de dök upp direkt.
Problem blir nu när jag startar den och den säger.
Typen Toolbar.myToolbar innehåller inte någon egenskap med namnet cc1:myToolbarItem.
Källfel:
<code>
<cc1:myToolbar id="MyToolbar2" style="Z-INDEX: 101; LEFT: 256px; POSITION: absolute; TOP: 96px"
runat="server">
<cc1:myToolbarItem Text="F" Value="F"></cc1:myToolbarItem></cc1:myToolbar>
</code>
min myToolbarCollection den ärva dessa?
<code>
public class MyToolbarCollection : ArrayList, IStateManager
{
private ArrayList _ToolbarItems = new ArrayList();
private bool _isTrackingViewState;
public void Add(myToolbarItem tItem)
{
_ToolbarItems.Add(tItem);
}
public myToolbarItem this[int index] 'this blir markerat och den säger, to make this current override...
{
get{return((myToolbarItem)this._ToolbarItems[index]);}
}
...
}
</code>Sv: __dopostback
"Eftersom informationen hur detta kan gå till <b>är tunn tänker
försöka</b> förklara hur det går till. "
? :-DSv: __dopostback
Word måste klippt bort lite ord skulle vara:
"Eftersom informationen hur detta kan gå till är tunn på nätet och i MS dikumentation tänker jag försöka förklara hur det går till. "
fixat detta nu. Tack!
Mvh JohanSv: __dopostback
Aaa nu är du inte på andra saker :-) kul.
Om du på din property för NodeCollection lägger till följande:
<code>
[PersistenceMode(PersistenceMode.InnerProperty),DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public NodeCollection Items...
</code>
Detta gör att du ditekt kan ange Nodes...
ex:
<code>
<cc1:NodeControl id......>
<Node attribut.......>
<Node attribut......>
</cc1:NodeControl>
</code>
Mvh Johan
Sv: __dopostback
En tvetydig matchning hittades.
Källfel:
<code>
<cc1:myToolbar id="MyToolbar9" style="Z-INDEX: 101; LEFT: 344px; POSITION: absolute; TOP: 80px"
runat="server">
<Items>
<cc1:myToolbarItem Text="as" Value="asd"></cc1:myToolbarItem>
</Items>
</code>
I min ToolbarControl så har jag
<code>
[PersistenceMode(PersistenceMode.InnerProperty),DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public virtual MyToolbarCollection Items 'ska denna vara virtual? Vad menas med det?
{
get { return (this._Items); }
set { this._Items = value;}
}
</code>Sv: __dopostback
Det betyder att du kan överskriva den vid arv.
ex köra override på den så som du gjorde med LoadViewState i din kontroll.
Matchnings fel? ser du rad?
Har lite mkt att göra nuså jag kan inte kolla din kod just nu.
Mvh JohanSv: __dopostback
Jag testade att lägga till en Item i min render metod.
<code>
myToolbarItem a = new myToolbarItem();
a.Value = "asdf";
Items.Add(a);
int ItemCount = this.Items.Count;
</code>
Nu borde ju Item.Count vara 1, men det är 0
När den addar så kör den först denna koden
<code>
[PersistenceMode(PersistenceMode.InnerProperty),DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public virtual MyToolbarCollection Items
{
get { return (_Items); }
set {_Items = value;}
}
</code>
och sen...
<code>
public void Add(myToolbarItem tItem)
{
_ToolbarItems.Add(tItem);
}
</code>
Nu borde ju this.Items.count vara 1.
men som sagt det är 0. Om jag istället skriver så här (och gör _ToolbarItems till public)
this.Items._ToolbarItems.count så får jag 1.
Så det sparas ner i _ToolbarItems.
I min ToolbarCollection har jag nog ett fel?
min klass ärver av arraylist, detta gör ju att hela blir en arraylist. Är detta rätt?
<code>
public class MyToolbarCollection : ArrayList, IStateManager
{
...
}
</code>
i min ToolbarCollection har jag även denna funktionen.
Här blir this understrukit och det står
"Toolbar.MyToolbarCollection.this[int] hides inherited member 'System.Collections.ArrayList.this[int]. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword."
<code>
public myToolbarItem this[int index]
{
get{return((myToolbarItem)this._ToolbarItems[index]);}
}
</code>Sv: __dopostback
I din kod i NodeCollection har du en metod som heter SaveViewState()
den ser ut som nedan och använder sig av this.Count för att bestämma storleken på arrayn
. Alltså måste NodeCollection ärva av ArrayList eller CollectionBase, eller?
Sen har du även en Add funktion som lägger till Noder i en arraylist (_NodeItems).
Eftersom this.Count inte går mot _NodeItems så får den ju alltid 0.
<code>
object System.Web.UI.IStateManager.SaveViewState()
{
object[] array1 = new object[this.Count];
for(int i=0;i<this.Count;i++)
array1[i] = ((IStateManager)this[i]).SaveViewState();
return array1;
}
</code>
<code>
public class MyToolbarCollection : CollectionBase, IStateManager
{
public ArrayList _ToolbarItems = new ArrayList();
private bool _isTrackingViewState;
#region Add
public void Add(myToolbarItem tItem)
{
_ToolbarItems.Add(tItem);
}
#endregion
</code>Sv: __dopostback
Oj. Sorry.
I min kod ärver jag ListDictionary
Jag skrev lite fel i artikeln, men du kan skapa engen count o returnera Arraylistens count värde,
skall nog gå lika bra.
Mvh JohanSv: __dopostback
För så fort jag autopostar sidan så försvinner mina items.
Som jag ser det så använder jag helt ditt exempel.
När jag lade till ListDictionary så kan jag inte lägga till Noder direkt i designen helller.
Add funktionen är disabled.
vill så gärna få detta att funka...Sv: __dopostback
Heheh.
Kollade på fel kod. Tittade på en ModulRegistratorns collection.
MenuNodeColelction vs ModuelNodeCollection. Tänkte väl att jag inte skrivit så fel i min artikel..
Som jag skrev är inte all kod med i artikeln då det är rätt mkt kod som skall skrivas försökte fokusera på det viktigaste staten.
Min NodeCollection ärver dessa Interface:
ICollection,IEnumerable, IStateManager
Jag utför även detta i slutet av min Add metod:
((IStateManager)node).TrackViewState();
min Count ser ur så här:
public int Count
{
get {return ( this._values.Count ); }
}
I övrigt bör koden fungera. Kan inte direkt se att jag missat nått.
Mvh JohanSv: __dopostback
Fått ordning på det?
Jag skrev inlägget om statebagen ur huvudet, så jag kan ha missat sake,r ber om ursäkt för det. Nu har det gått så lång tid så det är väl ingen mening att skriva om den.
Mvh JohanSv: __dopostback
Har precis kommit hem, har varit i stugan över helgen.
Kastade mig på datorn för att kolla detta nu.
var tvungen att implementera copyTo,SyncRoot,IsSynchronized,.IEnumerable.GetEnumerator()
Nu får jag att object reference not set to an instace of an object, när jag klickar på Items i propertyn för att lägga till nya Noder.
min add funktion ser ut så här
<code>
public void Add(Node node)
{
_nodeItems.Add(node);
((IStateManager)node).TrackViewState();
}
</code>
om jag prövar lägga till noder direkt i codebehind, så läggs det till men försvinner när jag autopostar
<code>
if(!IsPostBack)
{
Node a = new Node();
a.Value = "hej";
NodeControl6.Items.Add(a);
}
</code>