UserControl accessing DependencyProperty via RelativeSource Self - wpf

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

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.

Define Blend Expression ViewModel definition for RelativeSource binding

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>

How to add designmode dummy data into WPF control

Added entity Dummy to the usercontrol resources but Visual Studio complains it can't find resource 'Dummy'. Is it possible to add design data this way? What am I doing wrong?
<UserControl x:Class="MovieScraper.Media"
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:entity="clr-namespace:Processor.Entity;assembly=Processor"
mc:Ignorable="d"
d:DataContext="{StaticResource ResourceKey=Dummy}"
d:DesignHeight="300" d:DesignWidth="300" Background="White">
<UserControl.Resources>
<entity:Media x:Key="Dummy" Title="Akira"></entity:Media>
</UserControl.Resources>
<Grid>
<TextBlock Text="{Binding Title}"></TextBlock>
</Grid>
</UserControl>
I would create a MockDataContext model. This works pretty nice. This is a snippet from code that I have:
<UserControl x:Class="Modules.Core.Views.HeaderView"
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:viewModels="clr-namespace:Modules.Core.ViewModels"
mc:Ignorable="d"
d:DesignHeight="100" d:DesignWidth="1024">
<Grid d:DataContext="{d:DesignInstance Type=viewModels:MockHeaderViewModel, IsDesignTimeCreatable=True}">
</Grid>
</UserControl>
Big advantage is that you can actually run some code. For example I use it to update the time in my header in design time and vary some fields. You can immediately see if your binding work and your layout is giving you components enough space.
You are trying to bind d:DataContext to resource Dummy, but you are missing the keyword Binding. Please change this line to
d:DataContext="{Binding Source={StaticResource Dummy}}

Changing Silverlight view

I am trying to create a extension from an existing view where I have a list of text controls and in the new project I would like to use this control and change one of these text boxes to a radio button.
Using MVVM makes it easy to use the same code without having duplicated code, but for the XAML view I find no good way to do this change without creating a copy.
Example:
Core project with the main user control
<UserControl x:Class="SilverlightApplication4.MainPage" Name="test"
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"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<StackPanel>
<TextBlock>
asdfasdf
this is a test
</TextBlock>
<Button Height="120" Name="asdf" Content="This is a Button">
</Button>
</StackPanel>
</Grid>
</UserControl>
Now I have a second project where I want to change the TextBlock to something else.
<UserControl x:Class="SilverlightApplication1.MainPage"
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"
xmlns:core="clr-namespace:SilverlightApplication4;assembly=SilverlightApplication4" d:DesignHeight="300" d:DesignWidth="400">
<core:MainPage>
<!-- how do i change the type of child elements?-->
</core:MainPage>
</UserControl>
Solution will be to use a ContentControl and bind it to a ViewModel through Caliburn.Micro.
I added an example and code to my other question (below the XAML section): Project structure for EF/Silverlight application

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