I have two resources Dock and Undock in my View which is a UserControl(Dock.xaml), Following is xaml code
<Grid>
<ContentControl Template="{StaticResource Dock}"/>
</Grid>
In DockViewModel there is property called IsDocked,if its true i need to apply Dock otherwise Undock template
How to change the template in view using ViewModel.
<ContentControl>
<ContentControl.Style>
<Style TargetType="ContentControl">
<Setter Property="ContentControl.Template" Value="{StaticResource Dock}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsDocked}" Value="False">
<Setter Property="ContentControl.Template" Value="{StaticResource UnDock}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
Related
I'm struggling with setting DataContext of Usercontrol created using ControlTemplate.
In the code below I'd like the DriveControl's DataContext be set to it's parent's Datacontext field (pseudcode: DriveControl.DataContext = Parent.DataContext.DriveDataContext). Tried setting it in ControlTemplate itself or in Style with no luck.
I'm trying to do it in XAML alone.
<ContentControl>
<ContentControl.Resources>
<ControlTemplate x:Key="DriveTemplate">
<controls:DriveControl/>
</ControlTemplate>
<DataTemplate DataType="controls:DriveControl">
</DataTemplate>
<ControlTemplate x:Key="TimeTemplate">
<controls:TimeControl/>
</ControlTemplate>
<ControlTemplate x:Key="ApartamentTemplate">
<controls:ApartamentControl/>
</ControlTemplate>
</ContentControl.Resources>
<ContentControl.Style>
<Style TargetType="ContentControl">
<!--<Setter Property="Template" Value="{StaticResource DriveTemplate}"/>-->
<Style.Triggers>
<DataTrigger Binding="{Binding CurrentMode }" Value="Drive">
<Setter Property="Template" Value="{StaticResource DriveTemplate}"/>
</DataTrigger>
<DataTrigger Binding="{Binding CurrentMode }" Value="SetTime">
<Setter Property="Template" Value="{StaticResource TimeTemplate}"/>
</DataTrigger>
<DataTrigger Binding="{Binding CurrentMode }" Value="ChooseApartament">
<Setter Property="Template" Value="{StaticResource ApartamentTemplate}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
As suggested in a comment I was indeed overwriting DataContext in code behind. So simply putting
<controls:DriveControl DataContext="{Binding DriveDataContext}"/>
works - unless you're a dummy and forget the code you wrote earlier (to my defence - I was inspecting source of DataContext in Live Properties, but apparently "Go To Source" only works for XAML files). Lesson learned.
I have a listview with a Border wrapping a textbox (and other elements not shown in sample code). I want when the textbox is keyboard focused to change a property of the border that wraps it.
<ListView ItemsSource="{Binding activeLists}">
<ListView.ItemTemplate>
<DataTemplate>
<Border x:Name="border">
<TextBox Text="something">
<TextBox.Style>
<Style>
<Style.Triggers>
<Trigger Property="TextBox.IsFocused" Value="True">
<Setter TargetName="border" Property="TextBox.Background" Value="Red"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
If using inside the trigger TargetName="border" the item is not found.
If possible to do this from XAML only.
When I tried running this, I also got the error "TargetName property cannot be set on a Style Setter". Which indicates that you can't set a property of the Border control inside a style setter for the TextBox control (which doesn't honestly surprise me.)
What you can do instead is set it in the style of the border control itself, using a DataTrigger to bind to the IsFocused property of the textbox:
<Border>
<Border.Style>
<Style TargetType="Border">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsFocused, ElementName=textBox}" Value="true">
<Setter Property="Background" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<TextBox Name="textBox" Text="something"/>
</Border>
I want to assign a new DataTrigger programmatically (in code/not xaml) to every "TreeViewItem" style like I do in the following xaml.
I did some code (under xaml) where I defined my trigger but "ItemContainerStyle" is null. The function is called on Window Initialize event.
Anybody has an idea what I'm doing wrong ?
EDIT
I found some part of my problem: I moved my style from the "Resource" section to the "ItemContainerStyle" section as defined below in code sample. This way the style is still applied and I can access the style from the TReeView.ItemContainerStyle property in code. But I still don't know how to get the TreeViewItem selected style like the color of the background by code ??
I have xaml:
<TreeView Name="TreeViewSelectScopeStudy" MinHeight="24" Margin="7"
ItemsSource="{Binding Path=TvItemRootPssTreeViewRoot.ChildsView}" Height="Auto"
VerticalAlignment="Stretch"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Recycling">
<TreeView.Resources>
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="{Binding Path=IsExpanded}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsHilighted}" Value="true">
<!--<Setter Property="Background" Value="SlateBlue"></Setter>-->
<Setter Property="Background" Value="{StaticResource {x:Static SystemColors.HighlightBrushKey}}"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
I have that code:
public static void EnableMultipleSelection(TreeView treeView)
{
if (!_isMultiSelectTreeViewLeftButtonHandlerRegistered)
{
EventManager.RegisterClassHandler(typeof(TreeViewItem), UIElement.MouseDownEvent,
new MouseButtonEventHandler(TreeViewMouseDownGlobal));
_isMultiSelectTreeViewLeftButtonHandlerRegistered = true;
}
DataTrigger dataTrigger = new DataTrigger();
dataTrigger.Binding = new Binding("IsHilighted");
dataTrigger.Value = true;
dataTrigger.Setters.Add(new Setter(TreeViewItem.BackgroundProperty, new SolidColorBrush(Colors.Brown)));
treeView.ItemContainerStyle.Triggers.Add(dataTrigger);
Edited code:
<TreeView Name="TreeViewSelectScopeStudy" MinHeight="24" Margin="7"
ItemsSource="{Binding Path=TvItemRootPssTreeViewRoot.ChildsView}" Height="Auto"
VerticalAlignment="Stretch"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Recycling">
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="{Binding Path=IsExpanded}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsHilighted}" Value="true">
<Setter Property="Background" Value="{StaticResource {x:Static SystemColors.HighlightBrushKey}}"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</TreeView.ItemContainerStyle>
<TreeView.Resources>
<!--<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="{Binding Path=IsExpanded}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsHilighted}" Value="true">
<Setter Property="Background" Value="{StaticResource {x:Static SystemColors.HighlightBrushKey}}"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>-->
It sounds like you are trying to set the Style.Trigger too soon, before the template has been applied. If you apply the Trigger after the FrameWorkElement you are targeting has fully loaded you'll probably find that the ItemStyleContainer is no longer null.
http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.loaded.aspx
Implementing OnApplyTemplate for your FrameworkElement should hook you in after the ItemStyleContainer has been set as it is called after the Visual Tree has been rendered.
http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.onapplytemplate.aspx
I want to create a Trigger to be applied to all TextBox on Validation.HasError to show the Validation.Error in a custom ToolTip.
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="Background" Value="Red"/>
<Setter Property="ToolTip">
<Setter.Value>
<StackPanel>
<TextBlock Text="{Binding RelativeSource={RelativeSource XXX}, Path=(Validation.Error)[0].ErrorContent}"/>
</StackPanel>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
What should I put in the XXX?
My problem is that I don't really understand how RelativeSource works in this context and I can't get the correct code for binding to the TextBox.
I am guessing Self would refer to the TextBlock and FindAncestor x:Type TextBox will fail becuase it will traverse from TextBlock > StackPanel > Setter.Value > Setter > etc.. instead.
How can I refer to the Style Target instead?
Since ToolTip is not part of the visual tree, it's a bit cumbersome to get the behavior you want.
You can use its PlacementTarget property to find the element it is attached to, and set its DataContext to that element. In your case that will be a TextBox.
Now you can bind directly to the Validation.Errors property, and it will find the validation errors on a given TextBox.
You can use the following code to get it working:
<Window.Resources>
<ToolTip x:Key="errorTooltip"
DataContext="{Binding PlacementTarget,
RelativeSource={RelativeSource Self}}">
<StackPanel>
<TextBlock Text="{Binding (Validation.Errors)[0].ErrorContent}" />
</StackPanel>
</ToolTip>
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="Background" Value="Red"/>
<Setter Property="ToolTip" Value="{StaticResource errorTooltip}" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
This seems like a pretty common scenario but I can't figure out how to bind the menu items to disable when there is nothing in the clipboard.
I've decided against using the Windows clipboard and instead store the actual object in a reference variable on the UserControl called NodeClipboard. Since it is strongly typed and implements INotifyProperty it is a lot more useful to me than the Windows clipboard.
Binding to the individual item works fine though it is extremely verbose because you can't set EventHandlers within resources without using the Style Event Setters.
It sort of looks like this...
<UserControl x:Name="PART_Root">
<TreeView x:Name="PART_Tree" ItemsSource="{Binding ElementName=PART_Root, Path=RootItemContainer}">
<TreeView.Resources>
<ContextMenu x:Key="ContextMenu">
<ContextMenu.Style>
<Style TargetType="ContextMenu">
<!-- I use this event to select the tree view item otherwise it is actually pretty difficult to know what item you right clicked on -->
<EventSetter Event="Opened" Handler="ContextMenu_Opened"/>
</Style>
</ContextMenu.Style>
<MenuItem Header="Cut">
<MenuItem.Style>
<Style TargetType="MenuItem">
<EventSetter Event="Click" Handler="CutNode_Click"/>
<Style.Triggers>
<!-- This binding is fine because it binds to the item that was right clicked on -->
<DataTrigger Binding="{Binding Path=IsRoot}" Value="True">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</MenuItem.Style>
</MenuItem>
<MenuItem Header="Paste">
<MenuItem.Style>
<Style TargetType="MenuItem">
<EventSetter Event="Click" Handler="PasteNode_Click"/>
<!-- This binding always fails because ContextMenu lives outside of the logical tree -->
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=PART_Root, Path=NodeClipboard" Value="{x:Null}">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</MenuItem.Style>
</MenuItem>
</ContextMenu>
<Style TargetType="TreeViewItem">
<Setter Property="ContextMenu" Value="{StaticResource ContextMenu}"/>
</Style>
<HierarchicalDataTemplate DataType="{x:Type local:Node}" ItemsSource="{Binding Path=Children}">
<TextBlock Text="{Binding Path=Id}"/>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
</UserControl>
The key part that doesn't work is this here:
<!-- This binding always fails because ContextMenu lives outside of the logical tree -->
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=PART_Root, Path=NodeClipboard" Value="{x:Null}">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
I've tried using relative source which results in the same problem. The only solution I've thought of so far is making two context menus, one with Paste enabled and one without, and switching the context menu on the style on the TreeViewItem style's ContextMenu setter like so...
<TreeView.Resources>
<Style TargetType="TreeViewItem">
<Setter Property="ContextMenu" Value="{StaticResource ContextMenu_PasteEnabled}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=PART_Root, Path=NodeClipboard" Value="{x:Null}">
<Setter Property="ContextMenu" Value="{StaticResource ContextMenu_PasteDisabled}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TreeView.Resources>
Use the Clipboard class. Then you can use the ContainsText method to determine if there is any data on the clipboard.
http://msdn.microsoft.com/en-us/library/system.windows.forms.clipboard.aspx