J'ai fait quelque chose de similaire une fois: dessiner les lignes de la grille sur UserControl, puis ajouter des contrôles dessus. C'était pour une simple application de planification utilisée pour assigner qui travaillera quel quart dans le mois courant. Je devais avoir des en-têtes de colonne (jours) et des en-têtes de rangée (personnes) et une grille défilante à l'intérieur, à laquelle je pourrais ajouter/enlever des contrôles. Je ne sais pas dans quelle mesure ma solution vous aidera, mais c'est ici. J'ai utilisé HeaderedScrollViewer
de here. UCHeader
est un UserControl
avec des zones de texte avec des dates. La magie se produit dans le UC_GridLines
.
<Grid>
<lib:HeaderedScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" Background="AliceBlue">
<lib:HeaderedScrollViewer.TopHeader>
<lib:UCHeader Name="ucHeader"/>
</lib:HeaderedScrollViewer.TopHeader>
<lib:HeaderedScrollViewer.LeftHeader>
<Border BorderBrush="Black" BorderThickness="1,2,1,1">
<StackPanel Orientation="Vertical" Name="spRows" />
</Border>
</lib:HeaderedScrollViewer.LeftHeader>
<Grid Name="gridContentAll">
<Border Canvas.ZIndex="1" Background="Transparent"
BorderThickness="1,1,1,2" BorderBrush="Transparent">
<Grid ClipToBounds="True" Name="gridContent" Background="Transparent" />
</Border>
<Border Canvas.ZIndex="0" BorderThickness="1,1,1,2" BorderBrush="Black" Background="White">
<lib:UC_GridLines Name="ucGridLines" BorderThickness="0"/>
</Border>
</Grid>
</lib:HeaderedScrollViewer>
</Grid>
importants sont:
- Réglage
Background="Transparent"
pour le contrôle qui commande l'enfant contenant
- Réglage ZIndex correctement, de sorte que les contrôles sont présentés sur la grille.
- Réglage
SnapsToDevicePixels="True"
et UseLayoutRounding="True"
sur l'élément racine (par exemple la fenêtre)
UC_GridLines dans son fichier XAML n'a rien (seulement <Grid></Grid>
). Dessiner les lignes de la grille se passe dans le codebehind:
protected override void OnRender(DrawingContext drawingContext)
{
// VM contains data of the grid, used to draw gridlines
// such as number of days etc.
if (this.VM == null)
{
base.OnRender(drawingContext);
return;
}
double dpiFactor = 1;
try
{
Matrix m = PresentationSource.FromVisual(this)
.CompositionTarget.TransformToDevice;
dpiFactor = 1/m.M11;
}
catch { }
Pen pen = new Pen(Brushes.Black, 1 * dpiFactor);
double halfPenWidth = pen.Thickness/2;
GuidelineSet guidelines = new GuidelineSet();
double width = this.VM.Days.Count * this.VM.DayWidth - 16 * (this.VM.DayWidth/24);
double height = this.VM.RowHeight * rowCount;
for (int i = 1; i < this.VM.Days.Count; i++)
{
guidelines.GuidelinesX.Add(i * this.VM.DayWidth + halfDashPenWidth);
}
for (int i = 1; i < rowCount; i++)
{
guidelines.GuidelinesY.Add(i * this.VM.RowHeight + halfPenWidth);
}
drawingContext.PushGuidelineSet(guidelines);
for (int i = 1; i < this.VM.Days.Count; i++)
{
drawingContext.DrawLine(dashpen, new Point(i * this.VM.DayWidth, 0), new Point(i * this.VM.DayWidth, height));
}
for (int i = 1; i < rowCount; i++)
{
drawingContext.DrawLine(pen, new Point(0, i * this.VM.RowHeight), new Point(width, i * this.VM.RowHeight));
}
drawingContext.Pop();
}
Merci Arie - c'est vraiment utile. Je viens de remplacer la méthode OnRender pour le contrôle personnalisé et ajouté une grille. Une idée de comment je pourrais seulement montrer la grille pendant que l'utilisateur traîne activement pourtant? Cette méthode de rendu est uniquement appelée initialement, puis lorsque je redimensionne le contrôle. Idéalement, ce serait génial de pouvoir le montrer et le cacher. –
Peu importe - c'est en fait juste juste rester là. Je l'ai fait assez subtile. J'ai également dû ajouter base.OnRender (drawingContext) à la fin, sinon la performance de l'accrochage glisser/grille était vraiment mauvaise pour une raison quelconque. Merci encore pour l'exemple de code. –