[C# WinForms] User control laden in Panel: Parent aanpassen

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Tanuki
  • Registratie: Januari 2005
  • Niet online
Ik heb een panel in mijn form 'Main' waarin ik UserControls laad.

Nu wil ik als men op een button drukt een andere UserControl laden in die panel. Maar ik zit dan in de UserControl en niet in 'Main', dus ik kan niet bij de panel.

Is hier een standaard mechanisme voor? Of moet ik dan bijv. altijd this meegeven aan de constructor van de UserControl zodat ik de functie LoadControl(UserControl uc) kan aanroepen?

Ik heb dit topic wel gevonden, daar gebruiken ze een delegate: http://www.experts-exchan...s/C_Sharp/Q_22048326.html

Maar ik kan niet echt op een nette manier komen om dit toe te passen zonder code te dupliceren, het is net wat de topicstarter zegt in zijn startpost.

[ Voor 26% gewijzigd door Tanuki op 11-05-2010 08:31 ]

PV: Growatt MOD5000TL3-XH + 5720wp, WPB: Atlantic Explorer v4 270LC, L/L: MHI SCM 125ZM-S + SRK 50ZS-W + 2x SRK 25ZS-W + SRK 20ZS-W Modbus kWh meter nodig?


Acties:
  • 0 Henk 'm!

  • D-Raven
  • Registratie: November 2001
  • Laatst online: 10-09 20:32
Waarom gebruik je geen event? (ook een vorm van delegates)

Acties:
  • 0 Henk 'm!

  • lier
  • Registratie: Januari 2004
  • Laatst online: 22:34

lier

MikroTik nerd

D-Raven schreef op dinsdag 11 mei 2010 @ 08:38:
Waarom gebruik je geen event? (ook een vorm van delegates)
Precies, je laat je main form luisteren naar een event (dat je zelf kan definieren in je usercontrol) waarop je main form de andere control laadt. Is voor wat betreft verantwoordelijkheid het meest logische.

Eerst het probleem, dan de oplossing


Acties:
  • 0 Henk 'm!

  • JMaster
  • Registratie: December 2009
  • Laatst online: 13-07 17:06
lier schreef op dinsdag 11 mei 2010 @ 08:41:
[...]

Precies, je laat je main form luisteren naar een event (dat je zelf kan definieren in je usercontrol) waarop je main form de andere control laadt. Is voor wat betreft verantwoordelijkheid het meest logische.
Dit heet dacht ook wel het observer pattern.

Acties:
  • 0 Henk 'm!

  • Sebazzz
  • Registratie: September 2006
  • Laatst online: 15:32

Sebazzz

3dp

Bijna, http://stackoverflow.com/...erver-interface-pros-cons

[ Voor 7% gewijzigd door Sebazzz op 11-05-2010 10:39 ]

[Te koop: 3D printers] [Website] Agile tools: [Return: retrospectives] [Pokertime: planning poker]


Acties:
  • 0 Henk 'm!

  • Tanuki
  • Registratie: Januari 2005
  • Niet online
D-Raven schreef op dinsdag 11 mei 2010 @ 08:38:
Waarom gebruik je geen event? (ook een vorm van delegates)
C#:
1
2
3
4
5
6
7
public void LoadControl(UserControl uc)
{
    this.pnl.Controls.Clear();
    this.pnl.Controls.Add(uc);
    uc.Dock = DockStyle.Fill;
    uc.LoadControl += new LoadControlHandler(this.LoadControl);
}


Bovenstaand zou werken als ik niet UserControl zou gebruiken, maar CustomUserControl, waarin ik dus dat event definieer.

Maar als ik dat doe kan ik geen designer meer gebruiken. Via een interface kan ook niet, voor zover ik heb geprobeerd.

PV: Growatt MOD5000TL3-XH + 5720wp, WPB: Atlantic Explorer v4 270LC, L/L: MHI SCM 125ZM-S + SRK 50ZS-W + 2x SRK 25ZS-W + SRK 20ZS-W Modbus kWh meter nodig?


Acties:
  • 0 Henk 'm!

  • TeeDee
  • Registratie: Februari 2001
  • Laatst online: 22:40

TeeDee

CQB 241

l0c4lh0st schreef op dinsdag 11 mei 2010 @ 09:21:
[...]

C#:
1
2
3
4
5
6
7
public void LoadControl(UserControl uc)
{
    this.pnl.Controls.Clear();
    this.pnl.Controls.Add(uc);
    uc.Dock = DockStyle.Fill;
    uc.LoadControl += new LoadControlHandler(this.LoadControl);
}


Bovenstaand zou werken als ik niet UserControl zou gebruiken, maar CustomUserControl, waarin ik dus dat event definieer.

Maar als ik dat doe kan ik geen designer meer gebruiken. Via een interface kan ook niet, voor zover ik heb geprobeerd.
En waarom zou je niet kunnen inheriten van een UserControl?

Dus zoiets:
C#:
1
2
3
public partial class MyUserControl : UserControl
{
}

In MyUserControl gooi je een Event op, en in je MainForm subscribe je daarop. Even heel simpel gezegd.

Heart..pumps blood.Has nothing to do with emotion! Bored


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Is het niet gewoon dat je de verantwoordelijkheid op de verkeerde plek legt. Je UserControl zelf hoort niet verantwoordelijk te zijn om de program flow van zijn parent te bepalen.

Een UserControl is een representatie van een stukje data of process. Je UserControl zal een bepaald resultaat hebben ( Die je eventueel met events bekend kunt maken ). Afhankelijk van het resultaat zal de Controller/View moeten bepalen welke volgende stap in het process er genomen word.

edit:
Ik denk dat ik je post niet helemaal goed gelezen had. Je wilt iets als een Master/Detail control maken. Waar je in je Master iets doet en dan het Detail Scherm veranderd. Ook daar zul je goed na moeten denken waar je je verantwoordelijkheden legt. Als je Master verantwoordelijk is voor het kiezen van de Detail UserControl, dan zijn die dependant van elkaar, en dat wil je eigenlijk niet. Je kunt beter een MasterDetailController (o.i.d.) laten beslissen welk control er waar getoond word, dan kun je er in een andere View voor kiezen om een ander Detail view te gebruiken. Je kunt dan inderdaad of doormiddel van events of door middel van het observable pattern kunnen werken.

Uiteindelijk is er een andere class dan de MasterControl verantwoordelijk om te bepalen hoe het DetailObject getoond word.

[ Voor 46% gewijzigd door Woy op 11-05-2010 12:44 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • Tanuki
  • Registratie: Januari 2005
  • Niet online
TeeDee schreef op dinsdag 11 mei 2010 @ 12:09:
[...]

En waarom zou je niet kunnen inheriten van een UserControl?

Dus zoiets:
C#:
1
2
3
public partial class MyUserControl : UserControl
{
}

In MyUserControl gooi je een Event op, en in je MainForm subscribe je daarop. Even heel simpel gezegd.
Ah, dat heb ik nu gedaan en dat werkt wel. :) Ik was partial vergeten toen ik het de eerste keer probeerde. :)

PV: Growatt MOD5000TL3-XH + 5720wp, WPB: Atlantic Explorer v4 270LC, L/L: MHI SCM 125ZM-S + SRK 50ZS-W + 2x SRK 25ZS-W + SRK 20ZS-W Modbus kWh meter nodig?


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
l0c4lh0st schreef op dinsdag 11 mei 2010 @ 09:21:
C#:
1
2
3
4
5
6
7
public void LoadControl(UserControl uc)
{
    this.pnl.Controls.Clear();
    this.pnl.Controls.Add(uc);
    uc.Dock = DockStyle.Fill;
    uc.LoadControl += new LoadControlHandler(this.LoadControl);
}
Dit is erg gekke code, alleen de naam LoadControlHandler al. De usercontrol bepaald wat je voor nieuwe usercontrol gaat laden? Waarom doet ie dat zelf dan niet? ;) Ik weet niet wat je precies wil doen, maar een event dat omschrijft wat er nu precies is gebeurd, waarbij de listener bepaald wat er dan aangepast moet worden lijkt me een stuk beter. :p

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • Tanuki
  • Registratie: Januari 2005
  • Niet online
pedorus schreef op dinsdag 11 mei 2010 @ 19:32:
[...]

Dit is erg gekke code, alleen de naam LoadControlHandler al. De usercontrol bepaald wat je voor nieuwe usercontrol gaat laden? Waarom doet ie dat zelf dan niet? ;) Ik weet niet wat je precies wil doen, maar een event dat omschrijft wat er nu precies is gebeurd, waarbij de listener bepaald wat er dan aangepast moet worden lijkt me een stuk beter. :p
Maar als ik (bijvoorbeeld) een product kies in mijn UserControl 'ViewProducts' en ik wil daarna de UserControl 'ViewProductDetail' laden in de panel waar op dat moment 'ViewProducts' in staat, kan ik dat toch alleen maar aanroepen vanuit 'ViewProducts'?

PV: Growatt MOD5000TL3-XH + 5720wp, WPB: Atlantic Explorer v4 270LC, L/L: MHI SCM 125ZM-S + SRK 50ZS-W + 2x SRK 25ZS-W + SRK 20ZS-W Modbus kWh meter nodig?


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Nee dat wil je juist niet. Je hebt bijvoorbeeld een lijst Producten, die je representeert op het scherm door middel van het UserControl ProductView. Op het moment dat je daar een ander product kiest word er bijvoorbeeld een event ProductSelected getriggered. Een overkoepelend object ziet dat en vervangt het ProductView component door een ProductDetailView.

Het voordeel daarvan is, is dat je ook een andere View kunt maken met ProductView die de ProductDetailView niet op de plek van de ProductView neerzet, maar bijvoorbeeld een ProductSpecialDetailView ergens op een andere plek.

Je wil eigenlijk geen afhankelijkheden creëren tussen de controls

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • Tanuki
  • Registratie: Januari 2005
  • Niet online
Woy schreef op woensdag 12 mei 2010 @ 09:17:
Nee dat wil je juist niet. Je hebt bijvoorbeeld een lijst Producten, die je representeert op het scherm door middel van het UserControl ProductView. Op het moment dat je daar een ander product kiest word er bijvoorbeeld een event ProductSelected getriggered. Een overkoepelend object ziet dat en vervangt het ProductView component door een ProductDetailView.

Het voordeel daarvan is, is dat je ook een andere View kunt maken met ProductView die de ProductDetailView niet op de plek van de ProductView neerzet, maar bijvoorbeeld een ProductSpecialDetailView ergens op een andere plek.

Je wil eigenlijk geen afhankelijkheden creëren tussen de controls
Wat je zegt klinkt heel logisch, maar ik zie de toepassing in de praktijk nog niet zo goed denk ik.

Want hoe ga ik dan de Main form abonneren op die events?

Dan moet ik een reeks if/else gebruiken om te kijken welke events ik zou moeten handlen toch?
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
if (source is ProductView)
{
    ProductView v = (ProductView)source;
    v.ProductSelected += new ProductSelectedHandler(v_ProductSelected);
}
else if (source is ProductDetailView)
{
    ProductDetailView v = (ProductDetailView)source;
    v.PressedBack += new PressedBackHandler(v_PressedBack);
}
// etc etc

// En dan de usercontrol laden in de panel
pnl.Controls.Clear();
pnl.Controls.Add(source);
source.Dock = DockStyle.Fill;


Of sla ik nu helemaal de verkeerde weg in? Ik wil het graag goed doen, maar zonder dat ik dit snap heb ik er natuurlijk weinig aan het zo te doen.

Heeft de manier van werken die jij voorstelt ook nog een bepaalde naam of iets dergelijks? Dan kan ik er zelf ook op Googlen etc. :)

Of zou ik dan alle mogelijke events in een CustomUserControl class moeten definieren (waar al mijn usercontrols van erven) en daar altijd opnieuw op abonneren (op allemaal dus)?

[ Voor 8% gewijzigd door Tanuki op 12-05-2010 22:10 ]

PV: Growatt MOD5000TL3-XH + 5720wp, WPB: Atlantic Explorer v4 270LC, L/L: MHI SCM 125ZM-S + SRK 50ZS-W + 2x SRK 25ZS-W + SRK 20ZS-W Modbus kWh meter nodig?


Acties:
  • 0 Henk 'm!

  • Tanuki
  • Registratie: Januari 2005
  • Niet online
Bump. :)

PV: Growatt MOD5000TL3-XH + 5720wp, WPB: Atlantic Explorer v4 270LC, L/L: MHI SCM 125ZM-S + SRK 50ZS-W + 2x SRK 25ZS-W + SRK 20ZS-W Modbus kWh meter nodig?


Acties:
  • 0 Henk 'm!

  • roy-t
  • Registratie: Oktober 2004
  • Laatst online: 08-09 11:33
Ook een usercontrol heeft toch gewoon een parent:
Gets or sets the parent container of the control.
http://msdn.microsoft.com...ontrol.parent(VS.71).aspx

Hiermee kun je de parent opvragen, bij de parent je usercontrol verwijderen en een nieuw control toevoegen, of gaat dit fout?

(Of denk ik nu echt te simpel).

C#:
1
2
3
Control p = this.parent(); 
p.controls.clear();
p.controls.add(new Control());

[ Voor 17% gewijzigd door roy-t op 17-05-2010 10:35 ]

~ Mijn prog blog!


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
l0c4lh0st schreef op woensdag 12 mei 2010 @ 22:04:
[...]

Wat je zegt klinkt heel logisch, maar ik zie de toepassing in de praktijk nog niet zo goed denk ik.

Want hoe ga ik dan de Main form abonneren op die events?

Dan moet ik een reeks if/else gebruiken om te kijken welke events ik zou moeten handlen toch?
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
if (source is ProductView)
{
    ProductView v = (ProductView)source;
    v.ProductSelected += new ProductSelectedHandler(v_ProductSelected);
}
else if (source is ProductDetailView)
{
    ProductDetailView v = (ProductDetailView)source;
    v.PressedBack += new PressedBackHandler(v_PressedBack);
}
// etc etc

// En dan de usercontrol laden in de panel
pnl.Controls.Clear();
pnl.Controls.Add(source);
source.Dock = DockStyle.Fill;


Of sla ik nu helemaal de verkeerde weg in? Ik wil het graag goed doen, maar zonder dat ik dit snap heb ik er natuurlijk weinig aan het zo te doen.
Je hebt neem ik aan een bepekte set controls, en dus kun je gewoon de juiste events bij de juiste controls zetten.

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
ProductView view;
ProductDetailView detailView;

private void InitializeComponents()
{
    //...
    view = new ProductView();
    view.MySelectedEvent += View_ProductSelected;
    //....
    detailView = new DetailViews();
    detailView.MyOtherEvent += DetailView_SaveClicked;
    //...
}

void View_ProductSelected(object sender, EventArgs e)
{
   //Hide/Remove ProductView
   //Set Product on DetailView
   //Show/Add DetailView
}

void DetailView_SaveClicked(object sender, EventArgs e)
{
   //Hide/Remove DetailView
   //Show/Add ProductView
}

Zoiets bijvoorbeeld
Heeft de manier van werken die jij voorstelt ook nog een bepaalde naam of iets dergelijks? Dan kan ik er zelf ook op Googlen etc. :)
Je kunt eens zoeken op MVC, dat is niet de enige manier om het te doen, maar wel een algemeen geaccepteerde manier om de verantwoordelijkheden van je Interface/Domein te scheiden.
Of zou ik dan alle mogelijke events in een CustomUserControl class moeten definieren (waar al mijn usercontrols van erven) en daar altijd opnieuw op abonneren (op allemaal dus)?
Dat lijkt me niet de goede oplossing. Je moet dingen plaatsen waar ze logisch zijn. Als je een abstract usercontrol zou hebben waar je objecten kan selecteren ( Iets als een ListView bijvoorbeeld ), dan is het logisch dat je daar een ItemSelected event hebt. Maar het is niet logisch om in een generieke class specifiekere events te definieren.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • Tanuki
  • Registratie: Januari 2005
  • Niet online
Ik heb het nu volgens bovenstaande manier aangepakt.

Ik heb dus een class Main.cs die een Form is. Op die form staat een panel waarin usercontrols geladen kunnen worden. In de constructor van Main.cs maak ik al deze user controls aan, sla ze op als private data velden en abonneer Main op de custom events van de controls. Dan laat ik een usercontrol zien en dat is dan het eerste scherm.

Als er dan events worden opgegooid zet ik de juiste user control in de panel.

Nu heb ik nog wel een paar kleine vragen:
• Klopt het dat in dit geval mijn controller de cs file van elke user control is? Of moet ik er eigenlijk nog een controller bij maken die tussen de view en het model zit (wat dus op dit moment die cs file is). View is de designer met alle componenten.

• Als ik een view heb die een product laat zien doe ik view.Product = product; dan weet de view welk product hij moet gebruiken. Ik gebruik de volgende setter:
C#:
1
public Product Product { set { this.product = value; this.Configure(); } }
De Configure method stelt dan alle labels etc. in aan de hand van het opgegeven product. Liever zou ik het product meegeven aan de constructor, maar dan moet ik wel elke keer opnieuw een view maken (new ProductView(p)) en opnieuw abonneren op de events. Kan dit ook op een makkelijkere manier?

• Ik heb ook een scherm dat producten zoekt, hier kan ik dus niet vooraf iets meegeven dat de view kan gebruiken. Nu is mijn NHibernate class nog static, waardoor ik deze overal aan kan, maar eigenlijk wil ik dit in de toekomst veranderen naar een geïnstantieerd object. Het nadeel is dan dat ik in de SearchProductsView òf alle producten vooraf moet meegeven aan de constructor (of via een property) òf ik moet de NHibernate class (waar een functie in zit die de producten teruggeeft aan de hand van de zoekterm) meegeven aan de constructor. Beide manieren zijn niet echt netjes, denk ik.

PV: Growatt MOD5000TL3-XH + 5720wp, WPB: Atlantic Explorer v4 270LC, L/L: MHI SCM 125ZM-S + SRK 50ZS-W + 2x SRK 25ZS-W + SRK 20ZS-W Modbus kWh meter nodig?


Acties:
  • 0 Henk 'm!

  • Tanuki
  • Registratie: Januari 2005
  • Niet online
Bump? :)

PV: Growatt MOD5000TL3-XH + 5720wp, WPB: Atlantic Explorer v4 270LC, L/L: MHI SCM 125ZM-S + SRK 50ZS-W + 2x SRK 25ZS-W + SRK 20ZS-W Modbus kWh meter nodig?


Acties:
  • 0 Henk 'm!

  • Tanuki
  • Registratie: Januari 2005
  • Niet online
Bump? :)

PV: Growatt MOD5000TL3-XH + 5720wp, WPB: Atlantic Explorer v4 270LC, L/L: MHI SCM 125ZM-S + SRK 50ZS-W + 2x SRK 25ZS-W + SRK 20ZS-W Modbus kWh meter nodig?


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
l0c4lh0st schreef op woensdag 19 mei 2010 @ 15:52:
• Klopt het dat in dit geval mijn controller de cs file van elke user control is? Of moet ik er eigenlijk nog een controller bij maken die tussen de view en het model zit (wat dus op dit moment die cs file is). View is de designer met alle componenten.
Er zijn meerdere varianten op MVC, dus dit is een lastige vraag, maar het antwoord lijkt me nee. Waar het om gaat is dat je een usercontrol makkelijk wil kunnen hergebruiken. Dus stel dat je een usercontrol hebt die thumbnails van plaatjes laat zien. Al klik je op een plaatje dan vuurt de usercontrol een event. Het form waarop die usercontrol staat beslist vervolgens wat er nu moet gebeuren (zeg voorbeeld plaatje groter laten zien).

Maar misschien is het handiger om een aantal van die usercontrols met screenshots te plaatsen. Het lijkt een beetje op een browser-achtige situatie zo.
• Als ik een view heb die een product laat zien doe ik view.Product = product; dan weet de view welk product hij moet gebruiken. Ik gebruik de volgende setter:
C#:
1
public Product Product { set { this.product = value; this.Configure(); } }
De Configure method stelt dan alle labels etc. in aan de hand van het opgegeven product. Liever zou ik het product meegeven aan de constructor, maar dan moet ik wel elke keer opnieuw een view maken (new ProductView(p)) en opnieuw abonneren op de events. Kan dit ook op een makkelijkere manier?
Dit lijkt me toch normaal? :p Kijk anders eens in de code onder 'Windows Form Designer generated code'. Aan de constructor van zeg een Label wordt helemaal niks meegegeven.
• Ik heb ook een scherm dat producten zoekt, hier kan ik dus niet vooraf iets meegeven dat de view kan gebruiken. Nu is mijn NHibernate class nog static, waardoor ik deze overal aan kan, maar eigenlijk wil ik dit in de toekomst veranderen naar een geïnstantieerd object. Het nadeel is dan dat ik in de SearchProductsView òf alle producten vooraf moet meegeven aan de constructor (of via een property) òf ik moet de NHibernate class (waar een functie in zit die de producten teruggeeft aan de hand van de zoekterm) meegeven aan de constructor. Beide manieren zijn niet echt netjes, denk ik.
Ik snap het probleem niet helemaal. Alles meegeven aan de constructor lijkt me onzin en zeer slechte performance geven. Er zal altijd een manier moeten zijn om normaal te communiceren met je data layer.

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten

Pagina: 1