Set Diffrent DataContext to an Element in a ControlTemplate in WPF - wpf

I can't get any further.
My structure looks like this:
ViewModel (Class)
Property Number (Class, iValue)
Value, InputValidationInfo, etc.
Property Icon (Class, iValue)
Value, InputValidationInfo, etc.
The DataContext of the page is the ViewModel. There are input fields on the page. These are assigned to one of the iValues (Number, Icon). All input fields have a ContentTemplate. The ContentTemplate contains some elements which has bindings to the properties of the iValue-class.
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="border" Background="{TemplateBinding Background}">
<DockPanel>
<Border Width="10" Background="{Binding InputValidation, Converter={StaticResource InputValidationToBrushConverter}}" Margin="0">
<Border.ToolTip>
<ToolTip Visibility="{Binding InputValidationInfoCount, Converter={StaticResource CountToVisibleConverter}}" >
<ItemsControl ItemsSource="{Binding InputValidationInfo}"/>
</ToolTip>
</Border.ToolTip>
</Border>
<Border x:Name="ContentBorder" Margin="1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ContentPresenter Margin="5 1 0 1" x:Name="myButtonContent" HorizontalAlignment="Left" VerticalAlignment="Center" TextElement.Foreground="{StaticResource ButtonForegroundBrush}"/>
<StackPanel x:Name="Buttons" Grid.Column="1" Orientation="Horizontal" Visibility="Collapsed">
<Button x:Name="ResetButton" Style="{StaticResource styleInputBoxSubButton}" Content="{StaticResource symbolCancel}" FontFamily="{StaticResource symbolCancelFF}" Command="{Binding ResetValueCommand}"/>
</StackPanel>
</Grid>
</Border>
</DockPanel>
</Border>
</ControlTemplate>
And this is how it looks like:
<Button x:Name="btnIcon" Grid.Column="1" Grid.Row="2" DataContext="{Binding Icon}"
Style="{StaticResource styleInputButton}" MinHeight="37"
FontFamily="{Binding Value, Converter={StaticResource NumberToUserIconFontFamilyConverter}}"
Content="{Binding Value, Converter={StaticResource NumberToUserIconConverter}}"
Click="IconButton_Click"/>
My problem are the click events. The small [X] button is bound to the iValue classes with an ICommand. This works well. I can set the iCommand as binding in the ControlTemplate, because this is always the same iValue-property (ResetValueCommand).
But, a click of the "rest" of the actual button should call a method in the ViewModel. And the name of this method is not always the same. It cannot set in the ContentTemplate.
I cannot bind the command to the ViewModel, because the DataContext is already the iValue.
I have tried to use the Click event. But this event is also triggered by clicking the [X]-button.
This button should be used often. An elegant solution is needed. The most simple thing would be if I could specify the data context and binding for a particular element in the ContentTemplate in page-XAML. Or specify the click event of an element in the ContentTemplate in page-XAML.

I cannot bind the command to the ViewModel, because the DataContext is already the iValue ...
You can specify a source for the binding regardless of its DataContext:
<Button x:Name="btnIcon" ...
Command="{Binding DataContext.CommandPropertyOfViewModel,
RelativeSource={RelativeSource AncestorType=Page}}"/>

Related

ContextMenu - Strange behavior when using ItemContainerStyle

I'm having a strange issue with my ContextMenu. The ItemsSource is a List<Layer> Layers;, where the Layer class overrides the ToString() to return the Name property.
If I don't use any ItemContainerStyle for the context menu, it all works fine - it takes the Layer object and displays the ToString() of that object, like it should. When I add the ItemContainerStyle, it shows an empty string.
Here's the XAML:
<Style x:Key="myItemControlTemplate" TargetType="{x:Type MenuItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<Border SnapsToDevicePixels="True" Height="32" Width="200" Background="White">
<Grid VerticalAlignment="Center" Height="Auto" Width="Auto" Background="{x:Null}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="textBlock" HorizontalAlignment="Left" TextWrapping="Wrap" Text="{TemplateBinding Header}" VerticalAlignment="Top" Foreground="#FF3B3D52"
Grid.Column="1" Margin="6,0,0,0"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Button ContextMenuService.IsEnabled="False">
<Button.ContextMenu>
<ContextMenu FontFamily="Global Sans Serif" Height="Auto" Width="200" Padding="0,6" VerticalOffset="5" BorderThickness="0"
HasDropShadow="True" ItemContainerStyle="{StaticResource myItemControlTemplate}">
</ContextMenu>
</Button.ContextMenu>
</Button>
And here's how I fire it:
private void btn_Click(object sender, RoutedEventArgs e)
{
Button btn = sender as Button;
ContextMenu ctm = btn.ContextMenu;
ctm.ItemsSource = Layers;
ctm.PlacementTarget = btn;
ctm.Placement = PlacementMode.Bottom;
ctm.IsOpen = true;
}
Could it be that for some reason this binding gets busted somehow?
Text="{TemplateBinding Header}"
BTW, if I change the layers list to be a List<string> and just feed it the names of the layers, it works correctly with the ItemContainerStyle.
What am I missing?
The issue is the TemplateBinding. This is a less powerful but optimized variant of a relative source binding to a templated parent, but it comes at the expense of several limitations, like not supporting two-way binding. Although not officially stated in the documentation, it seems that this binding does not support conversion of the underlying type to string, as ToString is never called in this case.
Replace the TemplateBinding with a binding to the templated parent using relative source.
<TextBlock x:Name="textBlock"
HorizontalAlignment="Left" TextWrapping="Wrap"
Text="{Binding Header, RelativeSource={RelativeSource TemplatedParent}}"
VerticalAlignment="Top" Foreground="#FF3B3D52"
Grid.Column="1" Margin="6,0,0,0"/>

How can I set the binding for a control's property (which is inside DataTemplate and UserControl) to use the ItemSource's given property?

I would like to make a UserControl which have a DataTemplate, and inside that DataTemplate there are controls. I would like to bind to those nested (inside the DataTemplate) controls' properties so I can set them when I reuse this UserControl. The nested controls will use the ItemSource's properties but the property names of the ItemSource's properties could be different.
The UserControl:
<UserControl x:Class="ContextMenu.BaseFilterUserControl"
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"
x:Name="Self">
<Grid Margin="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80" />
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="70" />
</Grid.RowDefinitions>
<TextBlock Grid.Column="0"
VerticalAlignment="Center"
HorizontalAlignment="Right"
Margin="10"
Text="Owners" />
<Button Grid.Column="1"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Margin="10"
Click="FilteButtonClicked"
Width="40"
Height="40"
x:Name="FilterButton">
<Popup x:Name="FilterBoxPopup"
PlacementTarget="{Binding ElementName=FilterButton}"
Placement="Bottom"
StaysOpen="False">
<Border BorderBrush="Black"
Background="White"
Margin="2">
<ListView ItemsSource="{Binding ElementName=Self, Path=FilterList}"
x:Name="FilterListView"
Height="300"
Width="150">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<!--<CheckBox IsChecked="{Binding IsChecked}" />-->
<!--<TextBlock Text="{Binding Name}" />-->
<!--This is where I don't know how to properly bind eg. the above control, things I tried:-->
<!--<TextBlock Text="{Binding ElementName=FilterListView, Path=FilterElementName}" />-->
<!--<TextBlock Text="{Binding ElementName=Self, Path=DataContext.FilterElementName}" />-->
<!--<TextBlock Text="{Binding ElementName=FilterListView, Path=DataContext.FilterElementName}" />-->
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Border>
</Popup>
</Button>
<TextBlock Grid.Column="3"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="10"
Text="{Binding ElementName=Self, Path=SelectedNames}" />
</Grid>
</UserControl>
This how the UserControl is used, the FilterElementName="Name" is what I would like to set, depending on the list binded with FilterList list:
<local:BaseFilterUserControl FilterList="{Binding Owners}"
FilterElementName="Name"
SelectedNames="{Binding SelectedNames}"/>
In this case the Owners is a simple IReadOnlyList of an Owner class. The Owner class has a string Name property. But I will use this UserControl again with different list eg. where I would like to use the Versions list's Release property (for the TextBlock inside the UserControl):
<local:BaseFilterUserControl FilterList="{Binding Versions}"
FilterElementName="Release"
SelectedNames="{Binding SelectedReleases}"/>
The ListView is properly populated with items, so the FilterList DependencyProperty is working. But the nested controls are only working when I hard code the bindings:
<TextBlock Text="{Binding Name}" />
For this to work you would need to bind the Path-property of your TextBlocks Text-Binding to the FilterElementName property of your UserControl. Unfortunately the Path property of the Binding class is not a DependencyProperty and therefore not bindable.
One way to to achieve your goal would be to use the DisplayMemberPath property of the ListView, which is bindable:
<ListView x:Name="FilterListView"
Width="150"
Height="300"
ItemsSource="{Binding ElementName=Self, Path=FilterList}"
DisplayMemberPath="{Binding ElementName=self, Path=FilterElementName}"/>
If this approach does not work because you need to specify a more complex ItemTemplate, another way would be create a property of type DataTemplate in your UserControl, use that as ItemTemplate in the ListView and specify it from outside like so:
<local:BaseFilterUserControl FilterList="{Binding Versions}"
SelectedNames="{Binding SelectedReleases}">
<local:BaseFilterUserControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Release}" />
</DataTemplate>
</local:BaseFilterUserControl.ItemTemplate>
</local:BaseFilterUserControl>

WPF: Map UserControl properties to its children

The short version of my question is: Can properties of the UserControl be made available to the children of the UserControl without applying to the UserControl at the same time?
The long version: I am trying to create a "ButtonInput" which is a text box with a bitmap button at the right side, inside of the text box's border. This is pretty much how the search boxes look on many web sites (or in Visual Studio), with a magnifying glass at the right side.
The UserControl definition is:
<UserControl x:Class="Test.Controls.ButtonInput"
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:Test.Controls"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid Background="Transparent">
<Border
Name="Border"
CornerRadius="6"
Padding="4"
Margin="2 2 2 2"
Background="{Binding Path=Background, RelativeSource={RelativeSource FindAncestor, AncestorType=local:ButtonInput, AncestorLevel=1}}"
BorderBrush="{Binding Path=BorderBrush, RelativeSource={RelativeSource FindAncestor, AncestorType=local:ButtonInput, AncestorLevel=1}}"
BorderThickness="1"
>
<Grid Background="Transparent">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBox x:Name="tbInput"
Grid.Column="0"
MaxLines="1"
Background="Transparent"
Foreground="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType=local:ButtonInput, AncestorLevel=1}}"
Text="{Binding Path=Text, RelativeSource={RelativeSource FindAncestor, AncestorType=local:ButtonInput, AncestorLevel=1}}"
BorderThickness="0"/>
<Button Width="24" Grid.Column="1" Click="Button_Click">
<Button.Template>
<ControlTemplate>
<Image x:Name="imgIcon"
Source="{Binding Path=Source, RelativeSource={RelativeSource FindAncestor, AncestorType=local:ButtonInput, AncestorLevel=1}}" />
</ControlTemplate>
</Button.Template>
</Button>
</Grid>
</Border>
</Grid>
</UserControl>
I place this control in a test Window.
<Window x:Class="Test.TestWindow"
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:local="clr-namespace:Test"
xmlns:controls="clr-namespace:Test.Controls"
mc:Ignorable="d"
Title="TestWindow" Height="450" Width="800">
<Grid>
<StackPanel Orientation="Horizontal" Height="380" Width="402">
<Label Content="Password" Width="75" VerticalAlignment="Center"/>
<controls:ButtonInput x:Name="biTest" Source="Resources/img/password.png" Width="300" Height="35" Background="Orange" Foreground="Red" BorderBrush="Black" ButtonClick="ButtonInput_ButtonClick" />
</StackPanel>
</Grid>
</Window>
The problem I have is that I expect to have only what is inside the border colored orange, but instead the orange bleeds outside the border. I traced the problem to the way the Live Visual Tree looks like:
(ButtonInput)
(Border)
(ContentPresenter)
(Grid)
Border (Border)
(Grid)
tbInput (TextBox)
(Button)
The first Border is not in my control definition, but its background is Orange as inherited from the ButtonInput.
I did try an alternative: instead of using child controls for the content of the UserControl, I used a ControlTemplate with the same content. In this case, the executable looked OK (rounded rectangle with black border and orange background, no bleeding outside the border), but the designer in Visual Studio does not show anything. There is literally a blank space where the ButtonInput should be.
So, is there a way to prevent the properties set on the UserControl to apply to the first Border? Background is one example but there are other properties that I want to make use of the same way.
What's happening here is that your "ButtonInput" control isn't actually a button, it's a user control which just so happens to have a button on it. So when you set the background in the <controls:ButtonInput> tag on your main window you're effectively saying "ignore everything this user control says about the color of it's entire background because I'm now overriding it".
There are several ways around this, but the easiest one from the UserControl's perspective is to use the one last weapon in its arsenal: the template. Overriding the template in a control effectively says "I'm no longer going to be displayed the way a control of my type normally is, so all the usual settings won't apply unless I explicitly use them. That's as simple as doing this in your ButtonInput xaml:
<UserControl.Template>
<ControlTemplate>
<!-- all your old xaml code goes here -->
<Grid Background="Transparent">
<Border
Name="Border"
CornerRadius="6"
Padding="4"
<!-- etc -->
</ControlTemplate>
</UserControl.Template>
Which results in the following:
Truth be told, there are few cases in WPF where custom controls are actually needed, and this is almost certainly one of them. WPF is more than capable of supporting functionality like this with styles and templates alone. But this answer should suit your needs in the short term.
EDIT: If you want the control to be visible in the designer then populate it with a regular control and template that instead, it's what you probably should be doing anyway. Now your xaml should look like this:
<UserControl x:Class="WpfTestApp.Controls.ButtonInput"
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:WpfTestApp.Controls"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
x:Name="_this">
<UserControl.Resources>
<ControlTemplate x:Key="ButtonTemplate" TargetType="{x:Type Button}">
<Grid Background="Transparent">
<Border
Name="Border"
CornerRadius="6"
Padding="4"
Margin="2 2 2 2"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="1"
>
<Grid Background="Transparent">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBox x:Name="tbInput"
Grid.Column="0"
MaxLines="1"
Background="Transparent"
Text="{Binding ElementName=_this, Path=Text, Mode=TwoWay, NotifyOnTargetUpdated=True, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}"
Foreground="{TemplateBinding Foreground}"
BorderThickness="0" Margin="0,-1,0,1"/>
<Button Width="24" Grid.Column="1">
<Button.Template>
<ControlTemplate>
<Image x:Name="imgIcon" />
</ControlTemplate>
</Button.Template>
</Button>
</Grid>
</Border>
</Grid>
</ControlTemplate>
</UserControl.Resources>
<Button x:Name="biTest" Width="300" Height="35" Background="Orange" Foreground="Red" BorderBrush="Black" Template="{StaticResource ButtonTemplate}" />
</UserControl>
You haven't addressed the Text binding in your question, the code above is expecting a dependency property in the UserControl code behind:
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(ButtonInput), new PropertyMetadata(String.Empty));
And you now use it like this:
<controls:ButtonInput x:Name="biTest" Width="300" Height="35" Text="{Binding MyText, Mode=TwoWay}" />

Silverlight: How to set a ListBoxItem as selected only when a child control is clicked?

In a Silveright view, I have a ListBox, and each ListBoxItem within it contains a Hyperlink. By default, clicking anywhere on a ListBoxItem will highlight that item as selected. What I'd like to do is override the default selection behaviour, and make the Hyperlink inside each ListBoxItem act as the selection 'handle' for its parent, so that the ListBoxItem is only selected when the Hyperlink is clicked, while clicking anywhere else on the ListBoxItem has no effect. Is this possible and if so how could I achieve it?
The ItemTemplate of the ListBox:
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="LightGray" BorderThickness="1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".65*"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Grid.Row="1" Margin="5,0,0,0"
HorizontalAlignment="Left" VerticalAlignment="Center"
Text="{Binding UploadDate,
Converter={StaticResource DateDescriptionConverter}}"/>
<TextBlock Grid.Column="1" Grid.Row="0" Margin="5,0,0,0"
Text="{Binding HistoryStatus}"
HorizontalAlignment="Left" VerticalAlignment="Center"/>
<HyperlinkButton x:Name="DisplayDocument"
CommandParameter="{Binding}"
Grid.Column="2" Grid.Row="1" Content="View"
HorizontalContentAlignment="Left"
VerticalAlignment="Center" Margin="4">
<Interactivity:Interaction.Triggers>
<Interactivity:EventTrigger EventName="Click">
<Interactions:CallMethodAction
TargetObject="{Binding Path=DataContext,
ElementName=DocumentViewPanel}"
MethodName="ViewDocumentButtonClick"/>
</Interactivity:EventTrigger>
</Interactivity:Interaction.Triggers>
</HyperlinkButton>
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
To put this in some context, the contents of the ListBox is a list of documents, and clicking the Hyperlink loads the document in to a separate pane. With the default selection behaviour, by clicking the background of an item in the ListBox, the item can display as being selected without its corresponding document actually being loaded.
Thanks in advance for any answers.
I recommend you pick another control from the range of available base controls: I think the ItemsControl would be a good fit.
Why?
The ListBox is made to display a list of items and whenever you click anywhere on an item it will be selected. That's its purpose.
Apparently you don't want that - I'm not even sure you want the concept of "selection" at all.
As far as I understood: You want a visual list of items; each offering at least one action you can invoke for that very item and you want a visual indication that you have performed an associated action for an item.
Let's try to do this with an ItemsControl:
<ItemsControl>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
....
<Border
Background="Blue"
x:Name="DocumentDisplayed_Indicator"
Opacity="0"/>
<HyperlinkButton ...>
<Interactivity:Interaction.Triggers>
<Interactivity:EventTrigger EventName="Click">
<Interactions:CallMethodAction
TargetObject="{Binding Path=DataContext,
ElementName=DocumentViewPanel}"
MethodName="ViewDocumentButtonClick"/>
<SetPropertyAction
TargetName="DocumentDisplayed_Indicator"
Property="Opacity" Value="1"/>
</Interactivity:EventTrigger>
</Interactivity:Interaction.Triggers>
</HyperlinkButton>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

Validated Textbox in a UserControl

I have created a UserControl - a Labeled TextBox which is working pretty well, except for the validation template. When there's an error the validation control template shows up but it fills the whole space including the Label. I only want it to be as big as the TextBox. How to fix this?
Here's the xaml:
<UserControl x:Class="Infrastructure.CustomControls.LabelTextBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="LTB">
<Grid HorizontalAlignment="{Binding}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="tbl"
FontFamily="{Binding}"
FontSize="{Binding}"
Text="{Binding ElementName=LTB, Path=LabelText}"
Height="{Binding ElementName=LTB, Path=LabelHeight}"
Width="{Binding ElementName=LTB, Path=LabelWidth}"
VerticalAlignment="Center"/>
<TextBox x:Name="tbx"
Grid.Column="1"
FontFamily="{Binding}"
FontSize="{Binding}"
IsReadOnly="{Binding ElementName=LTB, Path=IsReadOnly}"
MaxLength="{Binding ElementName=LTB, Path=TextMaxLength}"
Text="{Binding ElementName=LTB, Path=Text}"
Height="{Binding ElementName=LTB, Path=TextHeight}"
Width="{Binding ElementName=LTB, Path=TextWidth}"
VerticalAlignment="Center">
<Validation.ErrorTemplate>
<ControlTemplate>
<DockPanel LastChildFill="True"
ToolTip="{Binding ElementName=aep, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
<TextBlock DockPanel.Dock="Right"
Foreground="Red"
FontSize="14pt" Text="*"
Margin="-15,0,0,0"
FontWeight="Bold"/>
<Border BorderBrush="Red" BorderThickness="1">
<AdornedElementPlaceholder Name="aep"/>
</Border>
</DockPanel>
</ControlTemplate>
</Validation.ErrorTemplate>
</TextBox>
</Grid>
</UserControl>
The reason why this happens is that you're implementing IDataErrorInfo in your view and not your UserControl. This causes the default WPF red border to appear for the entire usercontrol.
To get your defined error template to appear, you'll need to implement IDataErrorInfo in your usercontrol and add ValidatesOnDataErrors=True to your binding expression.
If you'd like to keep the IDataErrorInfo logic in your view and not in your UserControl (which is pretty reasonable), you'll need to define a validation template for the user control in the view:
<Window>
<local:UserControl>
<Validation.ErrorTemplate>
<ControlTemplate>
...
</ControlTemplate>
</Validation.ErrorTemplate>
</local:UserControl>
</Window>
To get it to only show the border for the TextBox, you can play with the border's width using a converter that'll take the entire usercontrol's width as a parameter and return the width of the textbox; possibly something like this:
<Border BorderBrush="Red" BorderThickness="1" Width="{Binding ElementName=ph, Path=ActualWidth, Converter={StaticResource myConverter}}">
<AdornedElementPlaceholder Name="ph" />
</Border>
Thanks for the response, it helped me figure out where the problem is. And for that i vote it as useful.
What i did was programmatically query the UserControl validation for errors in the TextBoxChangedEvent and set the validation error manually (http://wpftutorial.net/ValidationErrorByCode.html) for the TextBox.

Resources