How can i use MenuItem in TextBox data template in WPF? - wpf

<DataTemplate x:Key="RowItem" x:Name="RowItem">
<TextBox Text="{Binding Path=Content}">
<TextBox.ContextMenu>
<ContextMenu>
<MenuItem Header="Browse" Click="MenuItem_Click" />
</ContextMenu>
</TextBox.ContextMenu>
</TextBox>
</DataTemplate>
Now, all I need is: after browsing, I should get the selected file to be shown in this text box, but since its in a data template, I can't set the Text of the textbox because it has no id.
Note that I fill this data template at the code side with data rows.
Can anyone please help me? I have spent days on this problem.

Related

WPF - Show a tooltip if the length of the content of datagrid column is too long to fit in

I have a Data grid and I display some data in it. I want a tooltip to be displayed if the data that I want to fit in the column of the data grid is too long. All the solutions I found use a separate class to achieve that.
Is there a way to achieve the same thing with the help of a method only ?
I found the following solution in the link given.
Show WPF Tooltip if needed
<TextBlock Text="{Binding Text}">
<TextBlock.ToolTip>
<ToolTip
DataContext="{Binding Path=PlacementTarget, RelativeSource={x:Static RelativeSource.Self}}"
Visibility="{Binding Converter={StaticResource toolVisConverter}}">
<TextBlock Text="{Binding Text}"/> <!-- tooltip content -->
</ToolTip>
</TextBlock.ToolTip>
But it talks about a converter. Should I include that converter in view model or code behind file of .xaml file ?
at the same time, it says ti change the text block width in that converter. I don't know how to access Text block width in view model.
I am totally new to WPF. Can someone help pls ?

TreeListView.RowDetailsTemplate new for each row

Im close to my solution but i cant figure out my last step.
I have a RowDetailsTemplate for each row in a RadTreeListView.
My Probplem is I can figure out how to bind it. Im binding it to CurrentSelected but now evrytime I click on a other row the RowDetailsTemplate changes ofcourse. MY XAML is to big to post it so I ll show some examples.
<RadTreeListView Name="positionenDataGrid"
HierarchyColumnIndex="3"
ItemsSource="{Binding Path=Model.ModelChildList}"
SelectedItem="{Binding Path=CurrenPosition}">
<RadTreeListView.ChildTableDefinitions>
<TreeListViewTableDefinition ItemsSource="{Binding PositionChildList}" />
</RadTreeListView.ChildTableDefinitions>
<RadTreeListView.Columns>
<columns:CustomToggleButtonColumn x:Name="ExpanderColumn" Header="DetailView" DataMemberBinding="{Binding IsPositionExpanded}" ToggleButtonVisibility="{Binding Path=CanHavePositionen}"/>
</RadTreeListView.Columns>
<RadTreeListView.RowDetailsTemplate>
<DataTemplate>
<Views:DetailPositionView HorizontalAlignment="Left" />
</DataTemplate>
</RadTreeListView.RowDetailsTemplate>
</RadTreeListView>
Example of Binding in DetailPositionView;:
Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Views:ParentView}}, Path=DataContext.CurrenPosition.Number}"
If I open two RowDetailsTemplates at the same time they have both the same Content because I bind on the SelectedItem. The question now is: How can I give them each Data of each Row without SelectedItem?
DataContext of your DetailPositionView is the row data. So just doing
Value="{Binding Number}"
will do the trick

How to allow context menu to be multiple selection?

For a label, I have a list of items to show on context menu and can select many items.
Can it be a checkbox for each item on context menu?
Below is my current xaml codes:
<Label Content="{Binding Count}">
<Label.ContextMenu>
<ContextMenu ItemsSource="{Binding Items}" >
<ContextMenu.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</ContextMenu.ItemTemplate>
</ContextMenu>
</Label.ContextMenu>
</Label>
additional question: about remove the empty gap infront of the checkbox, I have used #Rohit reply already but it still has a line behind the checkbox item. Can it be delete?
Yeah you can have checkBox. Simply replace TextBlock with CheckBox.
<ContextMenu ItemsSource="{Binding Items}" >
<ContextMenu.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Name}" />
</DataTemplate>
</ContextMenu.ItemTemplate>
</ContextMenu>
Update for comment
how to remove an empty gap infront of the checkbox?
First please refrain from asking follow up questions in comments since it's not visible to larger audience here.
Now for your question - That's default template of ContextMenu which is getting applied. To avoid that you to override Template of ContextMenu. Refer to the template from here in case interested (modify it as per your needs)
However, there is quick and dirty way to achieve that by specifying negative left margin:
<CheckBox Margin="-35,0,0,0" Content="{Binding Name}" />

Registering a Region within an ItemTemplate

I'm writing a WPF application with Prism and I'm using MVVM,
Now, I have a view with Items Control, and I want each item to have a certain look, with an option to add a unique context menu per item.
so it look's like this so far:
<ItemsControl Grid.Column="1" ItemsSource="{Binding DeviceHolders}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Image Name="image" Source="{Binding ImageIndex, Converter={StaticResource ImageIndexToLargeImageBitmapSource}}" Margin="5" VerticalAlignment="Center" HorizontalAlignment="Center">
<Image.ContextMenu>
<ContextMenu <--THIS AS A UNIQUE REGION WHICH THE REGION NAME WILL BE string.format("{0}-{1}", "DeviceHolderRegion", DeviceHolder.ID)-->/>
</Image.ContextMenu>
</Image>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
As I wrote in the code, I want the context menu to register as a region with a unique name (for each device holder object I want to add a different context menu based on his type).
is there a way to do so?
Thanks.
I didn't know you could use a ContextMenu as a region - you learn something new every day!
Anyway, try the following:-
<ContextMenu>
<regions:RegionManager.RegionName>
<MultiBinding StringFormat="{}{0}-{1}">
<Binding Path="DeviceHolderRegion" />
<Binding Path="DeviceHolder.ID" />
</MultiBinding>
</regions:RegionManager.RegionName>
</ContextMenu>
I haven't tried running it, but VS XAML editor doesn't complain about the syntax, which is a promising start.

Binding To the Parent of A Context Menu Which is A Templated Grid

In a WPF .Net 4 application have a master detail situation where a datagrid has rows which can have the detail information as found in the RowDetailsTemplate which has an internal datagrid.
Within the RowDetailsTemplate is a grid to hold the sub details which has a context menu. The problem found is when binding the CommandTarget of one of the details' MenuItem, I am unable to target that details datagrid as generated by the template. The below binding ends up getting the Master datagrid and not the containing datagrid which is holding the details information/contextmenu.
<DataGrid x:Name="dgEditScript" ItemsSource="{Binding CurrentScript}">
<DataGrid.CommandBindings>
<CommandBinding Command="commands:ScriptingCommands.SetChecked"
Executed="CheckAllAfter" />
</DataGrid.CommandBindings>
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<DataGrid ItemsSource="{Binding SubCommands}">
<DataGrid.ContextMenu>
<ContextMenu>
<MenuItem Header="Check All From Selected"
Command="commands:ScriptingCommands.SetChecked"
CommandTarget="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}">
<MenuItem.Icon>
<Image Source="Images/checkboxes.png" />
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</DataGrid.ContextMenu>
</DataGrid>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
The problem when using the above Realtive source binding, it gives me the dgEditScript grid (top level) and not the parent of the context menu, the unnamed holding DataGrid which the context menu was launched from.
How do I get the sub grid in the binding; to target the parent of the context menu?
If I'm understanding your question right, you have a collections of items, and you want the context menu to be attached to the selected item (when you're right clicking on it ...)
Here's some similar code I'm using:
<ListBox x:Name="name_here"
ItemsSource="{Binding source_collection_name}"
SelectedItem="{Binding property_name_on_VM, UpdateSourceTrigger=PropertyChanged}"
>
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem Header ="Edit Item" Command="{Binding EditItem_Command}"
CommandParameter="{Binding property_name_on_VM}"
/>
<MenuItem Header ="Delete Item" Command="{Binding DeleteItem_Command}"
CommandParameter="{Binding property_name_on_VM}"
/>
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>
This way, whenever you click on an item (or right click), it's selected, and then you just send that item as a command parameter, so you have the item you need.
Hope this helps.

Resources