Je travaille sur un contrôle WPF personnalisé. Le but principal de ce contrôle est de visualiser des milliers de primitives graphiques dans une zone défilante. La partie principale du modèle du contrôle ressemble à ceci:Forcer la repeinte d'un UIElement personnalisé dans un contrôle WPF personnalisé
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:ItemVisualizer}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<local:ItemAreaElement Grid.Row="0" Grid.Column="0" x:Name="PART_ItemArea" />
<ScrollBar Grid.Row="0" Grid.Column="1" x:Name="PART_ScrollBarVert" Orientation="Vertical" Maximum="100" />
<ScrollBar Grid.Row="1" Grid.Column="0" x:Name="PART_ScrollBarHorz" Orientation="Horizontal" Maximum="100" />
<Rectangle Grid.Row="1" Grid.Column="1" x:Name="PART_SizeGrip" Focusable="False" Fill="#F0F0F0" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
La propriété ItemAreaElement est responsable du dessin des éléments. Pour simplifier, on peut penser que sa partie de base ressemble à ceci:
class ItemAreaElement : FrameworkElement
{
protected override void OnRender(DrawingContext drawingContext)
{
base.OnRender(drawingContext);
for (int i = 0; i < _data.ItemCount; i++)
{
drawingContext.DrawLine(_penLine, new Point(0, i * 10), new Point(100, i * 10));
}
}
}
J'ai besoin de repeindre le ItemAreaElement chaque fois une propriété liée à l'ensemble des changements de contrôle ItemVisualizer. Cependant, je n'ai pas trouvé un moyen de le faire dans WPF. Le bien savoir truc avec l'objet Dispatcher ne fonctionne pas dans mon cas:
private static void OnItemCountPropertyChanged(DependencyObject source,
DependencyPropertyChangedEventArgs e)
{
ItemVisualizer vis = (ItemVisualizer)source;
vis._itemArea.Dispatcher.Invoke(delegate { }, DispatcherPriority.Render);
}
, où _itemArea est une référence locale à l'ItemAreaElement obtenu dans OnApplyTemplate():
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
if (this.Template != null)
{
_itemArea = this.Template.FindName("PART_ItemArea", this) as ItemAreaElement;
_itemArea.Grid = this;
}
}
Y at-il d'autres façons de forcer une mise à jour de l'UIElement dans ma construction? Ou peut-être, je dois redessiner tout le contrôle pour le rendre possible?
Vous ne pouvez pas simplement appeler 'vis._itemArea.InvalidateArrange()' ou 'vis._itemArea.InvalidateVisual()'? – Clemens
Ou probablement juste définir 'FrameworkPropertyMetadataOptions.AffectsRender' sur l'enregistrement de la propriété ItemVisualizer? – Clemens
@Clemens, ItemVisualizer est un objet, pas une propriété. Mais 'UIElement.InvalidateVisual()' aide, je ne sais pas pourquoi je l'ai négligé. Vous pouvez poster ceci comme une réponse, pas un commentaire. – TecMan