Почему вы используете команды для этого вместо стандартных обработчиков событий? Это явно логика пользовательского интерфейса, которая принадлежит коду, а не ViewModel.
**** UPDATE **
В случае, если вы используете это в ControlTemplate, вы можете обрабатывать код элемента управления как свой код. Для подключения событий можно использовать шаблон TemplatePart и подключиться к специально названному элементу в OnApplyTemplate. Чтобы упростить предоставление размера (или чего-либо еще, что нужно вашей виртуальной машине), вы можете добавить DP для хранения соответствующего значения и привязать к нему свойство виртуальной машины. Это также позволяет выполнять двустороннюю привязку, если вам нужно что-то вроде установки начального размера с виртуальной машины.
// 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
}
...
}
Чтобы использовать это, вам нужно убедиться, что в вашем шаблоне есть элемент с правильными типом и именем, соответствующими атрибуту.
<local:MyContainer ContainerDimensions="{Binding Path=SavedSize}">
<local:MyContainer.Template>
<ControlTemplate TargetType="{x:Type local:MyContainer}">
<Grid>
<Border Background="{TemplateBinding Background}">
<ContentPresenter/>
</Border>
<ResizeGrip x:Name="PART_Resizer" HorizontalAlignment="Right" VerticalAlignment="Bottom"
Width="20" Height="20"/>
</Grid>
</ControlTemplate>
</local:MyContainer.Template>
</local:MyContainer>
Теперь вы можете поместить этот шаблон в любом месте, поскольку он не объявляет обработчики событий и поэтому не зависит от файла с выделенным кодом. Теперь у вас есть вся логика пользовательского интерфейса, инкапсулированная в конкретный класс пользовательского интерфейса, но вы все равно можете обращаться к нужным вам данным на вашей виртуальной машине, связывая ее.
Если вы думаете об этом, вы обычно взаимодействуете со встроенными элементами управления. Если вы используете Expander, вы не захотите передавать клики ToggleButton в вашу виртуальную машину и пытаться расширить элемент управления оттуда, но вы можете узнать, открыт ли или нет Expander, так что есть свойство IsExpanded, которое вы можете можно связывать, сохранять и загружать как данные.