J'ai un contrôle utilisateur personnalisé avec une zone de texte dessus et je voudrais exposer la ligne de base (du texte dans la zone de texte) snapline en dehors du contrôle personnalisé. Je sais que vous créez un concepteur (hérité de ControlDesigner) et que vous surchargez SnapLines pour avoir accès aux lignes sna, mais je me demande comment obtenir la base de texte d'un contrôle que j'ai exposé par mon contrôle utilisateur personnalisé.Snaplines de base dans les contrôles Winforms personnalisés
Répondre
Je viens d'avoir un même besoin, et je l'ai résolu comme ceci:
public override IList SnapLines
{
get
{
IList snapLines = base.SnapLines;
MyControl control = Control as MyControl;
if (control == null) { return snapLines; }
IDesigner designer = TypeDescriptor.CreateDesigner(
control.textBoxValue, typeof(IDesigner));
if (designer == null) { return snapLines; }
designer.Initialize(control.textBoxValue);
using (designer)
{
ControlDesigner boxDesigner = designer as ControlDesigner;
if (boxDesigner == null) { return snapLines; }
foreach (SnapLine line in boxDesigner.SnapLines)
{
if (line.SnapLineType == SnapLineType.Baseline)
{
snapLines.Add(new SnapLine(SnapLineType.Baseline,
line.Offset + control.textBoxValue.Top,
line.Filter, line.Priority));
break;
}
}
}
return snapLines;
}
}
De cette façon, cela crée en fait un sous-concepteur temporaire pour la subcontrol afin de savoir où le SnapLine de base « réelle » est.
Cela semblait raisonnablement performant dans les tests, mais si perf devient un problème (et si la zone de texte interne ne bouge pas), alors la majeure partie de ce code peut être extraite dans la méthode Initialize.
Cela suppose également que la zone de texte est un enfant direct de UserControl. S'il existe d'autres contrôles affectant la disposition, le calcul de décalage devient un peu plus compliqué.
Vous êtes sur la bonne voie. Vous aurez besoin de passer outre la propriété Snaplines dans votre DesignR et faire quelque chose comme ceci:
Public Overrides ReadOnly Property SnapLines() As System.Collections.IList
Get
Dim snapLinesList As ArrayList = TryCast(MyBase.SnapLines, ArrayList)
Dim offset As Integer
Dim ctrl As MyControl = TryCast(Me.Control, MyControl)
If ctrl IsNot Nothing AndAlso ctrl.TextBox1 IsNot Nothing Then
offset = ctrl.TextBox1.Bottom - 5
End If
snapLinesList.Add(New SnapLine(SnapLineType.Baseline, offset, SnapLinePriority.Medium))
Return snapLinesList
End Get
End Property
Dans cet exemple, le usercontrol contient une zone de texte. Le code ajoute un nouveau Snapline qui représente la ligne de base pour la zone de texte. L'important est de calculer correctement le décalage.
Comme une mise à jour de la réponse de Miral .. voici quelques-unes des "étapes manquantes", pour quelqu'un de nouveau qui cherche comment faire cela. :) Le code C# ci-dessus est presque prêt à l'emploi, à l'exception de la modification de quelques-unes des valeurs pour référencer le UserControl qui sera modifié.
Références possibles Nécessaires:
System.Design (@robyaw)
usings nécessaires:
using System.Windows.Forms.Design;
using System.Windows.Forms.Design.Behavior;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
Sur votre UserControl vous avez besoin l'attribut suivant:
[Designer(typeof(MyCustomDesigner))]
Ensuite, vous devez une classe "designer" qui aura le remplacement de SnapLines:
private class MyCustomerDesigner : ControlDesigner {
public override IList SnapLines {
get {
/* Code from above */
IList snapLines = base.SnapLines;
// *** This will need to be modified to match your user control
MyControl control = Control as MyControl;
if (control == null) { return snapLines; }
// *** This will need to be modified to match the item in your user control
// This is the control in your UC that you want SnapLines for the entire UC
IDesigner designer = TypeDescriptor.CreateDesigner(
control.textBoxValue, typeof(IDesigner));
if (designer == null) { return snapLines; }
// *** This will need to be modified to match the item in your user control
designer.Initialize(control.textBoxValue);
using (designer)
{
ControlDesigner boxDesigner = designer as ControlDesigner;
if (boxDesigner == null) { return snapLines; }
foreach (SnapLine line in boxDesigner.SnapLines)
{
if (line.SnapLineType == SnapLineType.Baseline)
{
// *** This will need to be modified to match the item in your user control
snapLines.Add(new SnapLine(SnapLineType.Baseline,
line.Offset + control.textBoxValue.Top,
line.Filter, line.Priority));
break;
}
}
}
return snapLines;
}
}
}
}
Un gros vote (j'aimerais pouvoir donner plus) parce que vous avez pris la peine de mentionner, vous devez mettre la classe ControlDesigner à l'intérieur de votre UserControl ET décorer votre classe UserControl avec l'attribut Designer qui dicte la classe ControlDesigner. Tout est logique une fois que vous voyez cela, mais pas avant. Cheers. –
Stuart - J'ai eu le même problème, c'est pourquoi j'ai ajouté à cette question. Je suis content que les infos supplémentaires aient pu vous aider! –
En essayant cela mais VS2012 ne reconnaît pas ControlDesigner, im en utilisant Winforms, et. Net 4.5 ive jamais fait cela auparavant, donc présumez que je fais quelque chose de mal, mais ne peut pas comprendre quoi? – f1wade
Version VB.Net:
Remarque: vous devez remplacer txtDescription
par la zone de texte ou un autre nom de contrôle interne que vous utilisez. et ctlUserControl
à votre nom usercontrol
<Designer(GetType(ctlUserControl.MyCustomDesigner))> _
Partial Public Class ctlUserControl
'...
'Your Usercontrol class specific code
'...
Class MyCustomDesigner
Inherits ControlDesigner
Public Overloads Overrides ReadOnly Property SnapLines() As IList
Get
' Code from above
Dim lines As IList = MyBase.SnapLines
' *** This will need to be modified to match your user control
Dim control__1 As ctlUserControl = TryCast(Me.Control, ctlUserControl)
If control__1 Is Nothing Then Return lines
' *** This will need to be modified to match the item in your user control
' This is the control in your UC that you want SnapLines for the entire UC
Dim designer As IDesigner = TypeDescriptor.CreateDesigner(control__1.txtDescription, GetType(IDesigner))
If designer Is Nothing Then
Return lines
End If
' *** This will need to be modified to match the item in your user control
designer.Initialize(control__1.txtDescription)
Using designer
Dim boxDesigner As ControlDesigner = TryCast(designer, ControlDesigner)
If boxDesigner Is Nothing Then
Return lines
End If
For Each line As SnapLine In boxDesigner.SnapLines
If line.SnapLineType = SnapLineType.Baseline Then
' *** This will need to be modified to match the item in your user control
lines.Add(New SnapLine(SnapLineType.Baseline, line.Offset + control__1.txtDescription.Top, line.Filter, line.Priority))
Exit For
End If
Next
End Using
Return lines
End Get
End Property
End Class
End Class
Merci à tous ceux de l'aide. C'était difficile à avaler. La pensée ayant une sous-classe privée dans chaque UserControl n'était pas très acceptable.
Je suis venu avec cette classe de base pour aider ..
[Designer(typeof(UserControlSnapLineDesigner))]
public class UserControlBase : UserControl
{
protected virtual Control SnapLineControl { get { return null; } }
private class UserControlSnapLineDesigner : ControlDesigner
{
public override IList SnapLines
{
get
{
IList snapLines = base.SnapLines;
Control targetControl = (this.Control as UserControlBase).SnapLineControl;
if (targetControl == null)
return snapLines;
using (ControlDesigner controlDesigner = TypeDescriptor.CreateDesigner(targetControl,
typeof(IDesigner)) as ControlDesigner)
{
if (controlDesigner == null)
return snapLines;
controlDesigner.Initialize(targetControl);
foreach (SnapLine line in controlDesigner.SnapLines)
{
if (line.SnapLineType == SnapLineType.Baseline)
{
snapLines.Add(new SnapLine(SnapLineType.Baseline, line.Offset + targetControl.Top,
line.Filter, line.Priority));
break;
}
}
}
return snapLines;
}
}
}
}
Ensuite, tirer votre UserControl de cette base:
public partial class MyControl : UserControlBase
{
protected override Control SnapLineControl
{
get
{
return txtTextBox;
}
}
...
}
Merci encore pour ce détachement.
Ceci est une solution belle et générique pour le problème. Je vous remercie. – abrahala
- 1. Contrôles personnalisés ASP.NET
- 2. Comment gérer les contrôles empilés dans les Winforms .NET?
- 3. Comment créer des contrôles personnalisés dans Silverlight?
- 4. contrôles personnalisés, la création dynamique
- 5. Ninject, ASP.NET et contrôles personnalisés
- 6. Où dois-je stocker les données de configuration pour les contrôles personnalisés (contrôles utilisateur)?
- 7. C# winforms distribue uniformément 3 contrôles
- 8. WinForms: nombre variable de contrôles TextBox dynamiques
- 9. Comment passer args d'événements personnalisés à l'asp standard: les contrôles
- 10. Comment créer des contrôles Web personnalisés Java?
- 11. Bonnes pratiques de création de contrôles personnalisés composites WPF
- 12. Styles personnalisés pour les widgets personnalisés dans Qt
- 13. Contrôles BindingSource dans WinForms - par rapport à LINQ, ADO.Net, etc?
- 14. Problèmes de DataGridView pour WinForms personnalisés avec l'ajout de colonnes
- 15. Contrôles personnalisés dans la question d'événement souris Windows Forms C#
- 16. Ajouter des contrôles personnalisés à movieplayer dans l'iPhone 3.0 SDK
- 17. Plusieurs contrôles personnalisés qui utilisent mouseMoved dans une fenêtre
- 18. Silverlight contrôles personnalisés de l'utilisateur et la propriété Dépendance d'émission
- 19. Est-ce que WPF a des contrôles équivalents pour tous les contrôles Winforms?
- 20. Ajouter des contrôles à WinForms dynamiquement dans un autre thread
- 21. Pourquoi les contrôles dans le panneau personnalisé (winforms C#) disparaissent-ils dans le concepteur?
- 22. Comment définir la directive de cache de sortie sur les contrôles personnalisés sans code à l'avant
- 23. Est-il possible d'injecter des contrôles personnalisés dans les pages JSP à l'aide d'une servlet?
- 24. Classe pour extraire automatiquement les champs de base de données dans les contrôles .NET
- 25. Éléments personnalisés dans ASP.NET avec des éléments enfants personnalisés
- 26. Concepteur WinForm et snapline à droite pour les contrôles dans le conteneur lors du redimensionnement
- 27. Comment gérez-vous les contrôles inutiles temporaires dans Winforms (masquage vs désactivation)?
- 28. Implémenter une fonctionnalité similaire au prototype pour les contrôles WinForms hébergés dans IE
- 29. Comment ajouter tous les contrôles d'un autre formulaire à un formulaire dans Winforms?
- 30. Classe de base commune pour les contrôles userc et les pages dans ASP.NET
Génial. Cela a fait ce que nous avions besoin de faire. Merci! – Mike
Nous avons plusieurs contrôles pour lesquels nous avions besoin de cela, donc nous avons fini par l'intégrer dans un concepteur commun pour les contrôles que nous avons implémenté une interface "ISnapable" que nous implémentons et exposons explicitement les contrôles. De cette façon, la logique est encore encapsulée dans le concepteur mais généralisée. – Mike