Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Why are you using commands for this instead of standard event handlers? This is clearly UI logic that belongs in code-behind, not a ViewModel.</p> <p>****UPDATE**</p> <p>In the case that you're using this in a ControlTemplate you can treat the Control's code as your code-behind. To do the connections of the events you can use the TemplatePart pattern and connect to the specially named element in OnApplyTemplate. To facilitate providing the Size (or whatever else your VM needs) you can add a DP to store the appropriate value and bind a VM property to that. This also allows for doing two way binding if you need to do something like set an initial size from the VM.</p> <pre><code>// this doesn't enforce the name but suggests it [TemplatePart(Name = "PART_Resizer", Type = typeof(ResizeGrip))] public class MyContainer : ContentControl { private ResizeGrip _grip; public static readonly DependencyProperty ContainerDimensionsProperty = DependencyProperty.Register( "ContainerDimensions", typeof(Size), typeof(MyContainer), new UIPropertyMetadata(Size.Empty, OnContainerDimensionsChanged)); private static void OnContainerDimensionsChanged(DependencyObject dObj, DependencyPropertyChangedEventArgs e) { MyContainer myContainer = dObj as MyContainer; if (myContainer != null) { Size newValue = (Size)e.NewValue; if (newValue != Size.Empty) { myContainer.Width = newValue.Width; myContainer.Height = newValue.Height; } } } public Size ContainerDimensions { get { return (Size)GetValue(ContainerDimensionsProperty); } set { SetValue(ContainerDimensionsProperty, value); } } static MyContainer() { DefaultStyleKeyProperty.OverrideMetadata(typeof(MyContainer), new FrameworkPropertyMetadata(typeof(MyContainer))); } public override void OnApplyTemplate() { _grip = Template.FindName("PART_Resizer", this) as ResizeGrip; if (_grip != null) { _grip.MouseLeftButtonDown += Grip_MouseLeftButtonDown; // other handlers } SizeChanged += MyContainer_SizeChanged; base.OnApplyTemplate(); } void MyContainer_SizeChanged(object sender, SizeChangedEventArgs e) { // update your DP } ... } </code></pre> <p>To make use of this you need to make sure you have an element in your template with the right Type and Name to match the attribute.</p> <pre><code>&lt;local:MyContainer ContainerDimensions="{Binding Path=SavedSize}"&gt; &lt;local:MyContainer.Template&gt; &lt;ControlTemplate TargetType="{x:Type local:MyContainer}"&gt; &lt;Grid&gt; &lt;Border Background="{TemplateBinding Background}"&gt; &lt;ContentPresenter/&gt; &lt;/Border&gt; &lt;ResizeGrip x:Name="PART_Resizer" HorizontalAlignment="Right" VerticalAlignment="Bottom" Width="20" Height="20"/&gt; &lt;/Grid&gt; &lt;/ControlTemplate&gt; &lt;/local:MyContainer.Template&gt; &lt;/local:MyContainer&gt; </code></pre> <p>You can now put this template anywhere since it's not declaring any event handlers and so is independent of a code-behind file. You now have all of your UI logic encapsulated in a UI specific class but can still access data you need in your VM by binding it.</p> <p>If you think about it this is the way you normally interact with built-in controls. If you use an Expander you wouldn't want to pass clicks of the ToggleButton into your VM and try to make the control expand from there, but you might want to know whether the Expander is open or closed, so there's an IsExpanded property that you can bind to and save and load as data.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload