I created a tabcontrol with TabItem dynamic, and each TabItem with a button to close it, but just want that button visible when the TabItem is selected.
But I can not access the control inside the DataTemplate
<TabControl Name="dynamicTab" ItemsSource="{Binding}" Margin="0,85,0,0">
<TabControl.Resources>
<DataTemplate x:Key="TabHeader" DataType="TabItem">
<DockPanel>
<Button
Focusable="False"
BorderThickness="0"
Background="Transparent"
BorderBrush="Transparent"
Padding="-4"
Height="10"
Width="10"
Name="btnDelete" Visibility="Hidden" DockPanel.Dock="Right" Margin="5,0,0,0" Click="btnDelete_Click"
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type TabItem}}, Path=Name}">
<Image Name="imgButtonClose" Source="/Recursos;component/Imagens/close16x16.png" Height="10" Width="10"/>
</Button>
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type TabItem}}, Path=Header}" />
</DockPanel>
</DataTemplate>
</TabControl.Resources>
</TabControl>
Just use the binding on the IsSelected property of ancestoral TabItem:
<BooleanToVisibilityConverter x:Key="boolToVisibilityConverter"/>
...
<Button ...
Name="btnDelete"
Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type TabItem}}, Path=IsSelected, Converter={StaticResource boolToVisibilityConverter}">
...
</Button>
If you have no problems with this binding:
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type TabItem}}, Path=Name}"
then the proposed code should work.
Related
I'm building a treeview with HierarchicalDataTemplates and would like to bind the nodes to a command from my MainViewModel. I guess there is some conflict with the scopes, since the binding works if I e.g. use a button and define it outside of the treeview. If I define it inside, however, it does not work.
I've searched through Stackoverflow and found several solutions but none that worked for me. Jehof e.g. suggested here to use
<Button Command="{Binding DataContext.Command,
RelativeSource={RelativeSource AncestorLevel=2, AncestorType=TreeViewItem}}"
CommandParameter="{Binding}" />
but that did not work. Thank you for any suggestions!
<TreeView ItemsSource="{Binding _questions}" Grid.Row="0" Margin="10" BorderThickness="1">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:Question}" ItemsSource="{Binding Converter={StaticResource QuestionConverter}}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Name}" />
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:MainOption}" ItemsSource="{Binding MainOptions}">
<StackPanel Orientation="Horizontal">
<CheckBox Content="{Binding Path=Name}" />
/////////////////////////////////////
<Button Command="{Binding ThisIsMyCommand}" Content="Click Me"/>
/////////////////////////////////////
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.Resources>
Is your TreeView-Control inside a Window or UserControl?
If you are inside a Window:
<Button Command="{Binding DataContext.Command, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" CommandParameter="{Binding}" />
and for UserControl
<Button Command="{Binding DataContext.Command, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}" CommandParameter="{Binding}" />
Are any controls or kind of, with selectedindexchanged event or property selecteditem maybe?
I use ContentPresenter now and me need some solution for getting index of selected item issue. With DataTemplate inside, it's desirable.
My code looks:
<Border BorderThickness="1">
<ContentPresenter Content="{Binding Path=Value}">
<ContentPresenter.Resources>
<DataTemplate DataType="{x:Type System:String}">
<TextBox Text="{Binding Path=Content, RelativeSource={RelativeSource AncestorType={x:Type ContentPresenter}}}"
TextAlignment="Left"
BorderThickness="0"/>
</DataTemplate>
<DataTemplate DataType="{x:Type System:Int32}">
<TextBox Text="{Binding Path=Content, RelativeSource={RelativeSource AncestorType={x:Type ContentPresenter}}}"
TextAlignment="Left"
BorderThickness="0"/>
</DataTemplate>
<DataTemplate DataType="{x:Type System:Double}">
<TextBox Text="{Binding Path=Content, RelativeSource={RelativeSource AncestorType={x:Type ContentPresenter}}}"
TextAlignment="Left"
BorderThickness="0"/>
</DataTemplate>
<DataTemplate DataType="{x:Type System:Boolean}">
<Border Background="White">
<CheckBox IsChecked="{Binding Path=Content, RelativeSource={RelativeSource AncestorType={x:Type ContentPresenter}}}"
HorizontalAlignment="Left"/>
</Border>
</DataTemplate>
</ContentPresenter.Resources>
</ContentPresenter>
</Border>
You need an ItemsControl or its derivates ListView, ListBox, DataGrid etc. They have SelectedItem property on them.
In order to set the ItemTemplate depending on the any criteria, use DataTemplateSelector and set Itemscontrol.Itemtemplateselector property. Details at msdn
http://msdn.microsoft.com/en-us/library/system.windows.controls.itemscontrol.itemtemplateselector(v=vs.110).aspx
I'm working with a WPF application to manage our main software's versions. This application has a ListBox, and I set the ListBox.DataTemplate to each ListBoxItem has a Label and 2 Buttons inside it.
The following code shows my ListBox code:
<ListBox Grid.Row="0" SelectedItem="{Binding Path=SelectedVersion}" ItemsSource="{Binding Path=PatchList, Mode=TwoWay}" d:DataContext="{d:DesignInstance {x:Type ViewModels:MainWindowViewModel}}"
SelectionMode="Single" IsSynchronizedWithCurrentItem="True" Margin="1" ScrollViewer.HorizontalScrollBarVisibility="Disabled" SelectedIndex="0">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Content="{Binding Path=VersionNumber}" HorizontalAlignment="Left" Foreground="#FFFFFF" FontSize="19" />
<Button Grid.Column="1" Width="25" Height="25" Template="{StaticResource OnMouseOverListBoxitem}" ToolTip="Release" Command="{Binding Path=DataContext.ReleaseVersionCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}}" HorizontalAlignment="Right" d:DataContext="{d:DesignInstance {x:Type ViewModels:MainWindowViewModel}}" CommandParameter="{Binding}">
<ContentControl Template="{StaticResource Release}" />
</Button>
<Button Grid.Column="2" Width="25" Height="25" Template="{StaticResource OnMouseOverListBoxitem}" ToolTip="Trash" Command="{Binding Path=DataContext.DeleteVersionCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}}" HorizontalAlignment="Right" d:DataContext="{d:DesignInstance {x:Type ViewModels:MainWindowViewModel}}" CommandParameter="{Binding}">
<ContentControl Template="{StaticResource Trash}" />
</Button>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The problem is that I would like to show the label and the buttons ONLY for the Selected ListBoxItem.
By the way, I'm using bindings, and if you see some different code it's because I'm also using MahApp.Metro for Windows8-style.
Any suggestions?
Thank you.
try this one.
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter1" />
</Window.Resources>
<Grid>
<ListBox ItemsSource="{Binding Fnts}" Grid.Row="0" SelectedItem="{Binding Path=SelectedVersion}"
SelectionMode="Single" IsSynchronizedWithCurrentItem="True" Margin="1" ScrollViewer.HorizontalScrollBarVisibility="Disabled" SelectedIndex="0">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Label Content="{Binding}" />
<Button Content=" X " Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}, Path=IsSelected, Converter={StaticResource BooleanToVisibilityConverter1}}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
How to display context menu for tree view item in wpf using the hierarchical data template? How to display context menu only for CountryTemplate:
<HierarchicalDataTemplate x:Key="DispTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Label}" Style="{StaticResource TreeTextStyle}" ToolTip="{Binding Path=Description}" Tag="{Binding Path=Tag}">
</TextBlock>
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="BuildingTemplate" ItemsSource="{Binding Path=Building}" ItemTemplate="{StaticResource BuildingTemplate}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Label}" Style="{StaticResource TreeTextStyle}" ToolTip="{Binding Path=Description}"/>
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="CityTemplate" ItemsSource="{Binding Path=City}" ItemTemplate="{StaticResource CityTemplate}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Label}" Style="{StaticResource TreeTextStyle}" ToolTip="{Binding Path=Description}"/>
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="CountryTemplate" ItemsSource="{Binding Path=Country}" ItemTemplate="{StaticResource CountryTemplate}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=RootName}" Style="{StaticResource TreeTextStyle}" ToolTip="{Binding Path=Description}"/>
</StackPanel>
</HierarchicalDataTemplate>
You also can add the ContextMenu to any visual child in the data template, for instance:
<HierarchicalDataTemplate x:Key="CountryTemplate" ItemsSource="{Binding Path=Country}" ItemTemplate="{StaticResource CountryTemplate}">
<StackPanel Orientation="Horizontal">
<StackPanel.ContextMenu>
<ContextMenu>
<MenuItem Header="Header" Command="{Binding Command}"/> <!--This command should be in the data context (each country item)-->
</ContextMenu>
</StackPanel.ContextMenu>
<TextBlock Text="{Binding Path=RootName}" Style="{StaticResource TreeTextStyle}" ToolTip="{Binding Path=Description}"/>
</StackPanel>
</HierarchicalDataTemplate>
One of the reasons why context menus do not work as cleanly as they could is because by default, they are in a different visual tree to everything else, so the DataContext cannot be found.
The key insight is to create a <Style> that defines a context menu,
then attach that style to a target element, which hooks up the context
menu. This shifts the context menu into a visual tree that is lined up with the default DataContext you want.
First, create the style:
<UserControl.Resources>
<ResourceDictionary>
<!-- For the context menu to work, we must shift it into a style, which means that the context menu is now in a
visual tree that is more closely related to the current data context. All we have to do then is set the style,
which hooks up the context menu. -->
<Style x:Key="ContextMenuStyle" TargetType="{x:Type StackPanel}">
<Setter Property="ContextMenu" Value="{DynamicResource TreeViewContextMenu}"/>
</Style>
<ContextMenu x:Key="TreeViewContextMenu">
<MenuItem Header="Test" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.CmdDisplayDetailsGraph}"/>
</ContextMenu>
Then, hook the context menu up anywhere you want, without running into issues caused by different visual trees.
Example 1:
<HierarchicalDataTemplate DataType="{x:Type snapshot:Details}" ItemsSource="{Binding DetailsList}">
<StackPanel Orientation="Vertical" Style="{StaticResource ContextMenuStyle}">
<ContentPresenter Content="{Binding}" ContentTemplate="{Binding View.DefaultDataRowTemplate}" />
</StackPanel>
Example 2:
<DataTemplate DataType="{x:Type snapshot:InstrumentDetails}">
<StackPanel Orientation="Vertical" Style="{StaticResource ContextMenuStyle}">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Center">
<HierarchicalDataTemplate x:Key="CountryTemplate" ItemsSource="{Binding Path=Country}" ItemContainerStyle="{StaticResource CountryTemplateItemContainerStyle}" ItemTemplate="{StaticResource CountryTemplate}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=RootName}" Style="{StaticResource TreeTextStyle}" ToolTip="{Binding Path=Description}" />
</StackPanel>
</HierarchicalDataTemplate>
<Style x:Key="CountryTemplateItemContainerStyle" TargetType="{x:Type TreeViewItem}">
<Setter Property="ContextMenu" Value="{DynamicResource TreeViewContextMenu}"/>
</Style>
<ContextMenu x:Key="TreeViewContextMenu">
<MenuItem .../>
</ContextMenu>
As you can see, you can add your contextmenu in the Itemcontainerstyle of the HierarchicalDataTemplate
Basically I came up with this
<HierarchicalDataTemplate x:Key="ChildTemplate">
<StackPanel Orientation="Horizontal">
<StackPanel.ContextMenu>
<ContextMenu>
<MenuItem Header="Copy" CommandParameter="{Binding CopyTag}">
</MenuItem>
<MenuItem Header="Paste" CommandParameter="{Binding PasteTag}">
</MenuItem>
<ContextMenu.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Command" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.CopyPaste}"/>
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
</StackPanel.ContextMenu>
<Image Source="/Images/Child.png" Stretch="None" VerticalAlignment="Center" HorizontalAlignment="Center" Style="{StaticResource TreeIconStyle}"/>
<TextBlock Text="{Binding Path=Label}" Style="{StaticResource TreeTextStyle}" ToolTip="{Binding Path=Description}" Tag="{Binding Path=Tag}">
</TextBlock>
</StackPanel>
</HierarchicalDataTemplate>
And have separate parameters for copy and paste to differentiate copy and paste in a single command.
I have written following xaml code:
<Window x:Class="WpfApplication3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="200" Width="200">
<StackPanel>
<ListBox Name="listBox">
<ListBoxItem Content="item1" />
<ListBoxItem Content="item2" />
<ListBoxItem Content="item3" />
</ListBox>
<TextBlock DataContext="{Binding ElementName=listBox, Path=SelectedItem}" Text="{Binding Content}" ToolTip="{Binding Content}" />
<TextBlock DataContext="{Binding ElementName=listBox, Path=SelectedItem}" Text="{Binding Content}">
<TextBlock.ToolTip>
<ToolTip Content="{Binding Content}"/>
</TextBlock.ToolTip>
</TextBlock>
</StackPanel>
</Window>
Why first tooltip always has the same text as it's parent TextBlock and second never changes it's content when I change selected item in listBox?
In the second example you're setting the ToolTip of the TextBlock to be a ToolTip. So you actually set the Content of the ToolTip to be another ToolTip. These would be the same as the first.
<TextBlock DataContext="{Binding ElementName=listBox, Path=SelectedItem}" Text="{Binding Content}" ToolTip="{Binding Content}" />
<TextBlock DataContext="{Binding ElementName=listBox, Path=SelectedItem}" Text="{Binding Content}">
<TextBlock.ToolTip>
<Binding Path="Content"/>
</TextBlock.ToolTip>
</TextBlock>
And these would pretty much be the same as the last
<Window.Resources>
<ToolTip x:Key="MyToolTip" Content="{Binding Content}"/>
</Window.Resources>
<TextBlock DataContext="{Binding ElementName=listBox, Path=SelectedItem}" Text="{Binding Content}" ToolTip="{Binding Source={StaticResource MyToolTip}}" />
<TextBlock DataContext="{Binding ElementName=listBox, Path=SelectedItem}" Text="{Binding Content}">
<TextBlock.ToolTip>
<ToolTip Content="{Binding Content}"/>
</TextBlock.ToolTip>
</TextBlock>