Define Blend Expression ViewModel definition for RelativeSource binding - wpf

I have an UserControl (MyCompositeView) where I add some other UserControls (MyDetailView). To get intellisense and refactoring ability I add to the CompositeView the d:DataContext in xaml.
To Manipulate the UserControl while adding them an new DataContext I bind the Visiblity to the RelativeSource (my CompositeViewModel). Unfortunately the matching against the MyCompositeViewModel isn't working for this Binding in the Editor.
Is there a way to let visual studio know that my DataContext of DataContext.DetailsIsVisible is from the type MyCompositeViewModel?
<UserControl
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
x:Class="Example.MyCompositeView"
d:DataContext="{d:DesignInstance Type=MyCompositeViewModel}"
d:DesignHeight="300"
d:DesignWidth="300"
mc:Ignorable="d">
<Grid>
<detail:MyDetailView
DataContext="{Binding Path=DetailViewModel}"
Visibility="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type UserControl}},
Path=DataContext.DetailsIsVisible,
Converter={StaticResource BooleanToVisibilty}}" />
</Grid>
</UserControl>
--
public class MyCompositeViewModel : IMyCompositeViewModel {
public bool DetailisVisible{get;set;}
public MyDetailViewModel DetailViewModel { get; }
}

Try binding by element name instead:
<UserControl
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
x:Class="Example.MyCompositeView"
x:Name="root"
d:DataContext="{d:DesignInstance Type=MyCompositeViewModel}"
d:DesignHeight="300"
d:DesignWidth="300"
mc:Ignorable="d">
<Grid>
<detail:MyDetailView
DataContext="{Binding Path=DetailViewModel}"
Visibility="{Binding ElementName="root"},
Path=DataContext.DetailsIsVisible,
Converter={StaticResource BooleanToVisibilty}}" />
</Grid>
</UserControl>
or flip the property order:
<UserControl
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
x:Class="Example.MyCompositeView"
d:DataContext="{d:DesignInstance Type=MyCompositeViewModel}"
d:DesignHeight="300"
d:DesignWidth="300"
mc:Ignorable="d">
<Grid>
<detail:MyDetailView
Visibility="{Binding DetailsIsVisible, Converter={StaticResource BooleanToVisibilty}}"
DataContext="{Binding DetailViewModel}"/>
</Grid>
</UserControl>

Related

WPF X:Name causes type name 'ViewModel' Compile Error

I intend to set a state of CalibrationGridControl from a button.
To do that, the CalibrationGridControl UserControl must have a x:Name (Blend even adds one for me when I setup the the GoToState behavior.
Problem is, as soon as I add x:Name="calibrationGridControl" I get the following compile error.
Error CS0426 The type name 'ViewModel' does not exist in the type 'TeachpendantControl' TeachPendantControl C:\GitRepos\SolutionName\TheWPFControl\Views\HandeyeCalibration\HandeyeCalibrationView.xaml 150 38 Build Active Compiler
The UserControl HandeyeCalibrationView below is a View to be shown inside a ContentControl in the "TheWPFControl". TheWPFControl and the HandyeCalibration.xaml are both in the same project (a WPF Control library). Below is the essential part of the HandeyeCalibration.xaml file where I get the error.
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:TeachpendantControl.ViewModel"
xmlns:local="clr-namespace:TeachpendantControl.Views"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:b="clr-namespace:Wpf.Behaviours"
xmlns:HandeyeCalibration="clr-namespace:TeachpendantControl.ViewModel.H"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
x:Class="TeachpendantControl.Views.HandeyeCalibrationView"
mc:Ignorable="d"
d:DataContext ="{d:DesignInstance {x:Type vm:HandeyeCalibrationViewModel},
IsDesignTimeCreatable=True}"
Height="111.221"
Width="276.813"
>
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../../ResourceDictionary.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<UserControl.DataContext>
<Binding Mode="OneWay"
Path="HandeyeCalibrationViewModel"
Source="{StaticResource Locator2}"/>
</UserControl.DataContext>
<Grid>
<UserControl>
...
<HandeyeCalibration:CalibrationGridControl
x:Name="calibrationGridControl"
HorizontalAlignment="Left"
Margin="0"
VerticalAlignment="Top"
Height="106"
Width="106"
Background="#FF747474"/>
<Button Command="{Binding AddCommand}"
Content="{Binding AddText, UpdateSourceTrigger=PropertyChanged}"
Margin="0,0,5,0">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:GoToStateAction TargetName="calibrationGridControl"
StateName="{Binding NextPositionState, Mode=OneWay}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</Grid>
</UserControl>
If I only remove the x:Name="calibrationGridControl" line everything compiles just fine. What could be wrong, causing this strange error message?
I got some questions about the CalibrationGridControl. If I just remove the x:Name when adding it to another user control everything compiles. The XAML for the CalibrationGridControl looks like this.
<UserControl x:Class="TeachpendantControl.ViewModel.H.CalibrationGridControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:TeachpendantControl.ViewModel"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity;assembly=System.Windows.Interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<SolidColorBrush x:Key="CalibrationGridCrossBrush" Color="#FFFFDF00"/>
<SolidColorBrush x:Key="CalibrationGridPositionTrainedFillBrush" Color="#FFFFDF00"/>
<SolidColorBrush x:Key="CalibrationGridPositionFillBrush" Color="Black"/>
</UserControl.Resources>
<Grid>
...
</Grid>
</UserControl>
TeachpendantControl apparently is both a type and a namespace.
You should either change the name of the control or the change the name of the namespace to avoid a naming collision.

ViewModel location into sub-folder (XAML, namespace)

Into MainWindow.xaml I have:
<Window x:Class="LayoutMVVM.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
ResizeMode="NoResize"
xmlns:local="clr-namespace:LayoutMVVM"
xmlns:veiwmodels="clr-namespace:LayoutMVVM.ViewModels"
xmlns:views="clr-namespace:LayoutMVVM.Views"
Title="Layout" Height="750" Width="650">
Into Windows.Resources I'm binding dataContext:
<Window.Resources>
<DataTemplate x:Name="SettingsTemp" DataType="{x:Type veiwmodels:SettingsModel}">
<views:SettingsView DataContext="{Binding}" />
</DataTemplate>
</Window.Resources>
But when my other model and view is located into sub-folder as below:
I can't do:
<DataTemplate x:Name="OpenTemp" DataType="{x:Type ViewModels:Open.OpenModel}">
<views:Open.OpenView DataContext="{Binding}" />
</DataTemplate>
or LayoutMVVM.ViewModels.Open.OpenModel
or LayoutMVVM/ViewModels/Open/OpenModel
You should add new one in header of control:
xmlns:veiwmodelsOpen="clr-namespace:LayoutMVVM.ViewModels.Open
or you can set namespace of OpenModel to LayoutMVVM.ViewModels (not LayoutMVVM.ViewModels.Open).
There is no other way, I think.

Extended WPF Toolkit zoombox disable zoom and reset

I am trying to use the extended toolkit Zoombox in my WPF Application with NET451.
I am using a tabcontrol for navigation and the items are bound to an observablecollection of ContentControls. When i change tab the content is changed but the zoomparameters are not reset. Also i want to disable zooming for certain tabitems. Binding to properties such as scale, minscale and maxscale does not seem to do the trick. My question is, how can i reset/go to home when changing view?
And how can i disable zoom for cetain tabitems?
XAML Looks like:
<Controls:MetroWindow x:Class="Metrotest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:toolkit="http://schemas.xceed.com/wpf/xaml/toolkit"
xmlns:local="clr-namespace:Metrotest"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Controls:MetroWindow.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVis" />
</Controls:MetroWindow.Resources>
<Grid>
<Grid.DataContext>
<local:MainViewModel/>
</Grid.DataContext>
<TabControl ItemsSource="{Binding tabitems}">
<TabControl.ContentTemplate>
<ItemContainerTemplate>
<Controls:FlipView
IsBannerEnabled="False"
ItemsSource="{Binding flipviewitems}" >
<Controls:FlipView.ItemTemplate>
<DataTemplate>
<toolkit:Zoombox ZoomOn="Content" x:Name="zoombox" AutoWrapContentWithViewbox="False" >
<ContentControl Content="{Binding flipview.Content}"/>
</toolkit:Zoombox>
</DataTemplate>
</Controls:FlipView.ItemTemplate>
</Controls:FlipView>
</ItemContainerTemplate>
</TabControl.ContentTemplate>
</TabControl>
</Grid>
</Controls:MetroWindow>

UserControl accessing DependencyProperty via RelativeSource Self

I have been having a problem using RelativeSource Self in a UserControl. I have contructed two UserControls that I thought would be identical in operation, but one works and the other doesn't. The User Controls themselves consist of just a label whose content I want to set to the DependencyProperty Title of the control. When I set the DataContext of the UserControl to RelativeSource Self, and bind the Label to Path=Title everything works fine. If however I bind the Label to RelativeSource FindAncestor, AncestorType{x:Type UserControl}}, Path=Title then it fails with a TargetInvocationException.
Any thoughts on what I am doing wrong.
This is XAML of the UserControl that works:
<UserControl x:Class="UserControlBinding.Controls.MyLabelControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<Label Content="{Binding Path=Title}"></Label>
</Grid>
</UserControl>
This is XAML of the code that fails
<UserControl x:Class="UserControlBinding.Controls.MyLabelControl2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:UserControlBinding.Controls"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Label Content="{Binding ReleativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MyLabelControl2}}, Path=Title}"></Label>
</Grid>
</UserControl>
Assuming the code for your Title property isn't causing a problem (can't tell since it's not listed) everything else looks ok except for the spelling: ReleativeSource -> RelativeSource

How can I display my user control in the MainWindow?

I'm trying to build a small MVVM test application, but can't really figure how to display my user control in the MainWindow.
My Solution Explorer:
I got a resource dictionary:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:MVVM.ViewModel"
xmlns:vw="clr-namespace:MVVM.View">
<DataTemplate DataType="{x:Type vm:ViewModel}">
<vw:View />
</DataTemplate>
</ResourceDictionary>
I got my view:
<UserControl x:Class="MVVM.View.View"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<DataTemplate x:Key="PersonTemplate">
<StackPanel>
<TextBlock Text="{Binding FirstName}" />
</StackPanel>
</DataTemplate>
</UserControl.Resources>
<ListBox ItemsSource="{Binding Path=Persons}"
ItemTemplate="{StaticResource PersonTemplate}" />
</UserControl>
and My MainWindow
<Window x:Class="MVVM.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:MVVM.ViewModel"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<ResourceDictionary Source="MainWindowResources.xaml" />
</Window.Resources>
<Grid>
</Grid>
</Window>
The most obvious and easiest way is to add the ContentControl element:
<Grid>
<ContentControl x:Name="mainContentControl" />
</Grid>
And after that set the Content property of this control to your view model, and the corresponding view will be loaded and applied automatically:
this.mainContentControl.Content = new ViewModel.ViewModel();
But I would prefer to use another way without datatemplates:
<Grid>
<vw:View x:Name="mainView"/>
</Grid>
this.mainView.DataContext = new ViewModel.ViewModel();
Build your VS2010 solution, then, go to your MainWindow's XAML.
On the left, there is a toolbar with button "Toolbox"
Open it, it contains all the possible WPF controls you could add to your UI
Your UserControl should appear on top of the list (in a category probably named "MVVM Controls"), just drag&drop it to your UI :)

Resources