How to show file context menu in a grid with files - c#

I've got a WPF grid in which each row represents a file on disk.
What I'd like to do is; when someone right-clicks on a row to show the same context menu as Windows Explorer shows. Any ideas how to implement this? I'm hoping that it will be relative easy but have not sure where to start with this.

Some clue...
<Window.Resources>
<Style TargetType="DataGridRow">
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu>
<ContextMenu.Template>
<ControlTemplate>
<TextBox Text="{Binding <the property with which column is bound to>}" Height="30" Width="40" />
</ControlTemplate>
</ContextMenu.Template>
</ContextMenu>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>

Related

How to remove ContextMenu border

So im trying to make button appear on right click in my ListBox.
<ListBox Grid.Column="1" Margin="358,44,20,63" Name="scriptbox" Background="#FF282828" Foreground="White" SelectionChanged="Scriptbox_SelectionChanged" BorderThickness="0">
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem
Template="{DynamicResource MenuItemTemplate}"
Header="Delete"
Click="MenuItemDelete_Click" >
</MenuItem>
</ContextMenu>
</ListBox.ContextMenu>
This is my MenuItem template.
<ControlTemplate TargetType="{x:Type MenuItem}" x:Key="MenuItemTemplate">
<Border x:Name="Border" Background="#FF282828" Padding="30,5,30,5" BorderThickness="0" Margin="0">
<ContentPresenter ContentSource="Header" x:Name="HeaderHost" RecognizesAccessKey="True" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsHighlighted" Value="true">
<Setter Property="Background" TargetName="Border" Value="#51544e"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<ItemsPanelTemplate x:Key="MenuItemPanelTemplate">
<StackPanel Margin="-3,0,0,0" Background="White"/>
</ItemsPanelTemplate>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="ItemsPanel" Value="{StaticResource MenuItemPanelTemplate}"/>
</Style>
Everything is fine but there is white border all around the button.
What you recognize as a white border is the ContextMenu itself that contains your MenuItems. Try adding more buttons and changing the Background and BorderBrush of the ContextMenu and you will see.
<ContextMenu Background="Red" BorderBrush="Blue">
Changing the brushes like this will lead to this result, which makes it obvious.
If you create a custom control template for your MenuItems you should probably do so for the ContextMenu, too, if only setting brushes does not fit your requirements. As you can see in the example, there is still a vertical white line that is part of the default control template, that you might want to get rid of. You can start from this example, although it is neither the default template nor complete. Look at this related post for guidance on how to extract the default control template for ContextMenu if you need it.

WPF MenuItem Icon sharing

I want to bind icons to the MenuItem controls where these items are dynamically created. I tried to set the x:Shared attribute to False but always only the last item has icon.
Here is my style for the MenuItems ItemContainerStyle code:
<Window.Resources>
<Style TargetType="{x:Type MenuItem}" x:Key="MenuItemStyle" x:Shared="False">
<Setter Property="Icon">
<Setter.Value>
<Image Source="{Binding IconSource}" />
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
And the MenuItem definition:
<MenuItem Header="Workspaces" ItemsSource="{Binding WorkspaceItems}" Icon="{StaticResource BranchIcon}" ItemContainerStyle="{StaticResource MenuItemStyle}" />
I have already tried to set this Shared attribute on the Image control but no luck.
Any suggestion?
You are almost there!
First of all: don't be confuse by Template vs Style.
When you are setting Icon property to an Image control, only one copy is created. As a control can have only one parent, it is removed from the previous parent each time it's re-assigned.
That's why you see only one icon.
You have 2 solutions for what you want:
use datatemplate instead, and redefine the whole Template of a MenuItem
use a style with a shared image component (what you tried to achieve)
In your example the only error is that the Shared attribute should be false on the Image resource, not on the whole style. This should work:
<Window.Resources>
<Image x:Key="MenuIconImage" x:Shared="false" Source="{Binding IconSource}"/>
<Style TargetType="{x:Type MenuItem}" x:Key="MenuItemStyle" BasedOn="{StaticResource {x:Type MenuItem}}">
<Setter Property="Icon" Value="{StaticResource MenuIconImage}">
</Setter>
</Style>
</Window.Resources>
Hope it helps.

WPF: PART_ContentHost not scrolling

I am trying to make a Log area within my application and the customer has requested the ability to cut/paste the log messages from this area.
I originally was using the following to setup the log area with scrolling, but this does not allow the user to select & copy text:
<ScrollViewer DataContext="{StaticResource Log}"
Content="{Binding Appender.Notification}"
Height="150">
<ScrollViewer.Resources>
<Style TargetType="{x:Type ScrollViewer}">
<Setter Property="HorizontalScrollBarVisibility" Value="Auto" />
<Setter Property="VerticalScrollBarVisibility" Value="Auto" />
</Style>
</ScrollViewer.Resources>
</ScrollViewer>
I found this solution to create a read only TextBox with select-able text:
<TextBox Name="LoggingTextBox"
Height="250"
Width="950"
DataContext="{StaticResource Log}"
Text="{Binding Appender.Notification}"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto">
<TextBox.Style>
<Style TargetType="TextBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border x:Name="PART_ContentHost" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TextBox.Style>
</TextBox>
This works to allow the selection of text within the log area but the scrolling does not work. I added the properties for *ScrollBarVisibility (not in the original solution).
How can I get the scrolling to work using this TextBox styling?
The fix is pretty simple: just change your Border to a ScrollViewer, and you will get the standard scrolling behavior for a TextBox.

WPF/Silverlight: How to add a command to a modified control template?

I have overridden a control template for a certain 3rd party control that I am using:
So
<Style TargetType="Some3rdPartyControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Some3rdPartyControl">
<Grid>
...alot of stuff..
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Basically, I have added a button inside the control template:
<Style TargetType="Some3rdPartyControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Some3rdPartyControl">
<Grid>
<Button x:Name="myButton" Width="20" Height="20">
...alot of stuff..
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Basically, I'd like to hook up an event, err probably a command to this new button... How do I do this? Which type of command is it, and where would it live? I don't have access to the actual .cs class of this third party control.So I'm hoping this command could live somewhere in a file that I generate, is this even possible?
You can have your command in your ViewModel and can bind that command to the button by simply using the RealtiveSource for binding like this -
<Style TargetType="Some3rdPartyControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Some3rdPartyControl">
<Grid>
<Button x:Name="myButton" Width="20" Height="20"
Command="{Binding DataContext.YourCommandName, RelativeSource={RealtiveSource FindAncestor, AncestorType={x:Type UserControl}}}">
...alot of stuff..
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Do you want a Command Property for your UserControl, or a static Command Definition?
If you want a Command Property, such as the Button.Command property, you need to create your own command definition in the code behind your UserControl. Look up creating your own custom DependencyProperty for that. The command that gets executed would "live" in whatever your DataContext was and the XAML code would look something like this:
<local:MyCustomControl SomeCustomCommand="{Binding SomeCommand}" />
If it's going to be a static Command Definition, like Copy or Paste commands, you need to create the static ICommand somewhere that the XAML can access, and bind the XAML with something like this:
<Button Command="{x:Static local:SomeCustomCommand}" />
This Command comes from the templated parent i.e. Some3rdPartyControl ...
Does your Some3rdPartyControl has a Command type depepdency property in it? If yes then you can do a TemplateBinding to that.
<Button x:Name="myButton" Command="{TemplateBinding Command}" Width="20" Height="20">
Else you will have to create a Command type attached property to your Some3rdPartyControl and use that to TemplateBinding to the Button.
<Style TargetType="Some3rdPartyControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Some3rdPartyControl">
<Grid>
<Button x:Name="myButton" Width="20" Height="20" Command="{TemplateBinding myNamespace:MyAttachedBehavior.MyAttachedCommand}">
...alot of stuff..
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Now while implementing your Some3rdPartyControl do this...
<Some3rdPartyControl myNamespace:MyAttachedBehavior.MyAttachedCommand="{Binding CommandFromDataContextViewModel}" />
CommandFromDataContextViewModel is your custom command. Due to TemplateBinding it reaches the Button and when Button click happnes this CommandFromDataContextViewModel command executes.
Does this answer your question?

WPF DataGrid Text wrapping in headers and elsewhere

I want to enable text wrapping in the WPF DataGrid column headers and the content of the rows.
Searching for solutions, I often stumble over something like this. The problem is, that it is not working for me.
First of all I have problems with this line:
xmlns:primitives="clr-namespace:Microsoft.Windows.Controls.Primitives;assembly=WPFToolkit"
I get errors about the assembly not being found.
More problems with the rest of the XAML-code.
<Style TargetType="{x:Type primitives:DataGridColumnHeader}">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock TextWrapping="Wrap" Text="{Binding}"></TextBlock>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
I place this inside the DataGrid tag, otherwise it won't compile. I also omit the "primitives"-namespace as I did not actually include it (see above). Now it compiles. However the application throws some exception in the constructor of the window. Any idea how I can get this thing to actually work?
Please see this first Text wrapping in WPF DataGrid column header
The reference to app.xaml is not required as can be seen here:
<DataGrid Name="WBdataGrid" AutoGenerateColumns="False" ColumnHeaderHeight="50" >
<DataGrid.ColumnHeaderStyle>
<Style TargetType="DataGridColumnHeader">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock TextWrapping="Wrap" Text="{Binding}"></TextBlock>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGrid.ColumnHeaderStyle>
<DataGrid.Columns>

Categories

Resources