Wpf Treeview Contextmenu DataContext - wpf

I am trying to set the Datacontext of my Contextmenu - but my Code does not work. Very similar code works at another location, so I would be grateful if somebody could explain why it does not work.
My Treeview looks like this:
Beware: it is rather long, but I think the nested structure is part of the problem, so I do want to shrink it.
The Problem occurs on the second "level" at the ppChart Binding.
<TreeView x:Name ="Presentation_SlidesWithIndex" Grid.ColumnSpan="1" HorizontalAlignment="stretch" Height="auto" Margin="0,0,3,0" VerticalAlignment="stretch" Width="auto" Tag="{Binding DataContext, ElementName=LayoutRoot}">
<TreeView.ItemContainerStyle>
<!--expand Charts when they contain elements-->
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="{Binding HasCharts}"/>
</Style>
</TreeView.ItemContainerStyle>
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type pp:PPSlide}" ItemsSource="{Binding Charts}">
<StackPanel x:Name="PPSlideElements" Orientation="Horizontal">
<StackPanel.Style>
<Style TargetType="{x:Type StackPanel}">
<Style.Triggers>
<!--Trigger for Slides with Charts-->
<DataTrigger Binding="{Binding Path=HasCharts}" Value="True" >
<Setter Property="Background" Value="LightBlue" />
</DataTrigger>
<!--Trigger for Slides with NO Charts-->
<DataTrigger Binding="{Binding Path=HasCharts}" Value="False" >
<Setter Property="Opacity" Value=".5" />
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<TextBlock FontSize="15">
<Run Text="Slide "></Run>
<Run Text="{Binding Path=Index}"></Run>
</TextBlock>
<!--<Image Source="/Images/pptIcon.png" Height="10"></Image>-->
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type pp:PPChart}" ItemsSource="{Binding ExcelSource}">
<StackPanel x:Name="PpChartElements" Orientation="Horizontal" AllowDrop="True" cal:Message.Attach="[Event Drop] = [Action DropItem($eventArgs,$view)]" Tag="{Binding DataContext, RelativeSource={RelativeSource AncestorType=UserControl}}">
<StackPanel.Style>
<Style TargetType="{x:Type StackPanel}">
<Style.Triggers>
<!--Trigger for Charts with DataSource set-->
<DataTrigger Binding="{Binding Path=HasDataSourceSet}" Value="True" >
<Setter Property="Background" Value="LightGreen" />
</DataTrigger>
<!--Trigger for Charts with DataSource nit set-->
<DataTrigger Binding="{Binding Path=HasDataSourceSet}" Value="False" >
<Setter Property="Background" Value="Orange" />
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<Image Source="{Binding ChartType, Converter={StaticResource PowerPointChartTypeConverter}}" Width="19" Height="19" Margin="2,2,4,2"></Image>
<TextBlock FontSize="14" Text="{Binding Path=ShapeName}" VerticalAlignment="Center">
<TextBlock.ContextMenu>
<ContextMenu cal:Action.TargetWithoutContext="{Binding Path=PlacementTarget.Tag.AddEntityCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}">
<MenuItem Header="Löse Verknüpfung" cal:Message.Attach="DeleteLink($datacontext)" ToolTip="Löscht einen bestehenden Link zu einer Excel Datei"/>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
<Image Source="{Binding PowerPointWriteStatus, Converter={StaticResource PowerPointWriteStatusConverter}}" Width="19" Height="19" Margin="2,2,4,2" ToolTip="Zeigt erfolg oder misserfolg des Erstellens an"></Image>
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type pp:PPSourceExcelLink}">
<StackPanel x:Name="PpSourceExcelLinkStackPanel" Orientation="Vertical">
<TextBlock FontSize="14">
<Run Text="Datei: "></Run>
<Run Text="{Binding Path=ExcelFileName, Mode=OneWay}"></Run>
</TextBlock>
<TextBlock FontSize="14">
<Run Text="Tabelle: "></Run>
<Run Text="{Binding Path=SourceTableID}"></Run>
</TextBlock>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>

I think your problem lies exactly in this line of code:
cal:Action.TargetWithoutContext="{Binding Path=PlacementTarget.Tag.AddEntityCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
To fix it you need to change this to:
cal:Action.TargetWithoutContext="{Binding Path=PlacementTarget.Tag.AddEntityCommand, RelativeSource={RelativeSource Self}}"
but this alone won't fix your problem because the target of the action message will be the TextBlock which doesn't have its Tag property set.
Anyway you should end up with code similar to this:
<TextBlock FontSize="14" Text="{Binding Path=ShapeName}" VerticalAlignment="Center" Tag="{Binding DataContext, RelativeSource={RelativeSource Self}}">
<TextBlock.ContextMenu>
<ContextMenu cal:Action.TargetWithoutContext="{Binding RelativeSource={RelativeSource Self},Path=PlacementTarget.Tag}">
<MenuItem Header="Löse Verknüpfung" cal:Message.Attach="DeleteLink($datacontext)" ToolTip="Löscht einen bestehenden Link zu einer Excel Datei" />
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
I answered a similar question recently and you can take a look at for more details.

I found a Solution which works fairly well - but why it works is beyond me:
<TextBlock FontSize="14" Text="{Binding Path=ShapeName}" VerticalAlignment="Center" Tag="{Binding DataContext, RelativeSource={AncestorType=TreeView}}">
<TextBlock.ContextMenu>
<ContextMenu cal:Action.TargetWithoutContext="{Binding RelativeSource={RelativeSource Self},Path=PlacementTarget.Tag}">
<MenuItem Header="Löse Verknüpfung" cal:Message.Attach="DeleteLink($datacontext)" ToolTip="Löscht einen bestehenden Link zu einer Excel Datei" />
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
Note how the Ancestertype treeview is used. my bet guess is that it walks the Visual tree until it finds the Treeview, which has the proper DataContect.
Thanks to Sniffer, which did a very good job !

As stated in RelativeSource binding from a ToolTip or ContextMenu there is no need to add the tag to the PlacementTarget. This makes it shorter, as there is no need to add a tag to the control and to the binding path of the ContextMenu, e.g.:
<TextBlock FontSize="14" Text="{Binding Path=ShapeName}" VerticalAlignment="Center">
<TextBlock.ContextMenu>
<ContextMenu cal:Action.TargetWithoutContext="{Binding Path=PlacementTarget, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Löse Verknüpfung" cal:Message.Attach="DeleteLink($datacontext)" ToolTip="Löscht einen bestehenden Link zu einer Excel Datei" />
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
and in the ViewModel
public void DeleteLink(object parameter)
{
if (parameter == null)
return;
var param = parameter as YourDataContextType;
if (! (param is YourDataContextType))
return;
// your delete handling
}

Related

Add doubleclick-command to wpf-treeview-items

as I found a lot of tasks (questions) to my question, I still have no idea how that works.
Even it's a much too complex example or simply the needed namespace was missing. So after one hour of research, my question...
How do I intergrate doubleclick-command to my WPF treeview (-items)?
Actually, my tree looks like this:
<!-- used Namespace: xmlns:i="http://schemas.microsoft.com/xaml/behaviors" -->
<TreeView DataContext="{Binding ProjectTree}" ItemsSource="{Binding ProjectNode}" DockPanel.Dock="Left"
x:Name="ProjectTree" Margin="0 0 2 0" Grid.Column="0">
<TreeView.ContextMenu>
<ContextMenu StaysOpen="True">
<MenuItem Header="Löschen" Height="20"
Command="{Binding RemoveNodeCommand}"
CommandParameter="{Binding ElementName=ProjectTree, Path=SelectedItem}">
<MenuItem.Icon>
<Image Source="/Icons/32x32/Remove_32x32.png" Width="15" Height="15"/>
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</TreeView.ContextMenu>
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectedItemChanged">
<i:InvokeCommandAction Command="{Binding TreeNodeSelectedCommand}"
CommandParameter="{Binding ElementName=ProjectTree, Path=SelectedItem}"/>
</i:EventTrigger>
<i:EventTrigger EventName="MouseDoubleClick">
<i:InvokeCommandAction Command="{Binding UpdateNodeCommand}"
CommandParameter="{Binding ElementName=ProjectTree, Path=SelectedItem}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}"/>
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
<Setter Property="FontWeight" Value="Normal"/>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="FontWeight" Value="Bold"/>
</Trigger>
</Style.Triggers>
</Style>
</TreeView.ItemContainerStyle>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal">
<Image Margin="3" Source="{Binding ItemType, Converter={x:Static misc:TreeItemImageConverter.Instance }}" Width="20" />
<TextBlock VerticalAlignment="Center" Text="{Binding Name}"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
I don't really understand how the Interaction.Triggers work but should they be the right way?
I'm using the ICommand and a relaycommand for my menu- and button-commands. So far, everything fine in my viewmodels.
Sorry if that is a noob question.
EDIT
As it wasn't a noob question but a noob typo, MouseDoubleClick simply works as SelectedItemChanged so my question was unneccessary. (updated code above)
You can add an interaction trigger in the data template.
I don't have your code so I've adapted a project I already had hanging about to show this working.
My markup, which is of course illustrative rather than cut and paste ready for your purposes:
<TreeView Name="tv" ItemsSource="{Binding Families}" Grid.Row="1" Grid.ColumnSpan="2"
>
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:Family}" ItemsSource="{Binding Members}">
<Border>
<StackPanel Orientation="Horizontal"
Height="32"
>
<Label VerticalAlignment="Center" FontFamily="WingDings" Content="1"/>
<TextBlock Text="{Binding Name}" />
</StackPanel>
</Border>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type local:FamilyMember}">
<ContentControl>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<i:InvokeCommandAction Command="{Binding DataContext.TestCommand, RelativeSource={RelativeSource AncestorType=TreeView}}"
CommandParameter="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType=TreeViewItem}}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<StackPanel Orientation="Horizontal"
Height="32"
x:Name="sp">
<TextBlock Tag="{Binding DataContext.Name,
RelativeSource={RelativeSource AncestorType=TreeViewItem , AncestorLevel=2}
}"
Text="{Binding Name}" />
<TextBlock Text="{Binding Age}" Foreground="Green" />
</StackPanel>
</ContentControl>
</DataTemplate>
</TreeView.Resources>
</TreeView>
The command in my window viewmodel
public class MainWindowViewModel
{
private DelegateCommand<FamilyMember> testCommand;
public ICommand TestCommand
{
get
{
if (testCommand == null)
{
testCommand = new DelegateCommand<FamilyMember>((member) =>
{
MessageBox.Show($"Member's name is {member.Name}");
});
}
return testCommand;
}
}
My tree has family and then each has family members.
If I expand members out I can double click a family member and the message box confirms the name is correct.
Note the contentcontrol in the datatemplate.
You need a control to give you double click support.
Interaction triggers cannot be applied in style setters but you could create an attached behaviour that handles the MouseDoubleClick event for the TreeViewItem:
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="local:YourBehavior.Command" Value="{Binding YourCommand}" />
...
</Style>
Another option is to invoke the command programmtically from the code-behind of the view.

How to add CheckBox content from resource file in wpf?

I have a combobox in which first item is checkbox to select all entries from below drop down list. With hard coded string its working fine but now I want to localize it...want to set string from resource file but as its deeply inserted couldn't add it. For that I tried adding panel and one checkbox along with textblock also simply separated textblock from checkbox.
This is code :
<ComboBox Name="CmbEntries" IsTabStop="{Binding CurrentDialogViewModel, Converter={StaticResource NullToBoolConverter}}" Grid.Column="1" Grid.Row="4" VerticalAlignment="Top" Margin="2,0,0,5" SelectedItem="{Binding SelectedEntries}" SelectedIndex="0" HorizontalAlignment="Left" Width="400">
<ComboBox.Resources>
<CollectionViewSource x:Key="EntriesCollection" Source="{Binding DicomDir.Entries}"/>
</ComboBox.Resources>
<ComboBox.ItemsSource>
<CompositeCollection>
<ComboBoxItem>
<CheckBox x:Name="all" Margin="8,0,0,0"
IsChecked="{Binding IsAllEntriessSelected, Mode=TwoWay}"
Command="{Binding SelectAllEntriessCommand}"
CommandParameter="{Binding IsChecked, RelativeSource={RelativeSource Self}}"
**Content="Select All Entries"** />
</ComboBoxItem>
<CollectionContainer Collection="{Binding Source={StaticResource EntriesCollection}}"/>
</CompositeCollection>
</ComboBox.ItemsSource>
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox Margin="8,0,0,0"
IsChecked="{ Binding Path=IsAnyEntitySelected, Mode=TwoWay }"
Command="{Binding SelectAllEntityCommand}"
CommandParameter="{Binding IsChecked, RelativeSource={RelativeSource Self}}" />
<TextBlock Margin="5,0,0,0" TextWrapping="Wrap" Text="{Binding DisplayEntriesInfo}"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
<ComboBox.ItemContainerStyle>
<Style TargetType="ComboBoxItem">
<Style.Triggers>
<DataTrigger Binding="{Binding HasSelectedEntities}" Value="True">
<Setter Property="FontWeight" Value="Bold"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>
Scrshot1-Expected
Scrshot2-Actual with Resx
In this case, is it possible to read it directly from resource file?
To bind the content to a resource you do:
<Window ...
xmlns:properties="clr-namespace:YourNamespace.Properties">
<Grid>
<CheckBox Content="{x:Static properties:Resources.Foo}" />
</Grid>
</Window>
For this to work you need Resources to be public.
If it is not you get:
Provide value on 'System.Windows.Markup.StaticExtension' threw an exception...
StaticExtension value cannot be resolved to an enumeration, static field, or static property.

ContextMenu too-wide WPF

I have built a ContextMenu dynamically using MVVM. The problem is : the content of MenuItems is all in right side ==> too wide ContextMenu. Do you have any ideea which is the problem? Thanks
Here is the code in XAML:
<TreeView.ContextMenu>
<ContextMenu Name="RightClickMenu" ItemsSource="{Binding Path=SelectedItem.MenuItemsList}">
<ContextMenu.ItemTemplate >
<DataTemplate>
<!-- <MenuItem HorizontalAlignment="Left" Header="{Binding Name}" Command="{Binding Command}" -->
<StackPanel Orientation="Horizontal">
<Image Source="{Binding MyIcon}" Width="18" Height="18" SnapsToDevicePixels="True" />
<MenuItem Header="{Binding Name}" Command="{Binding Command}"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type TreeView}}, Path=DataContext.SelectedItem}"
/>
</StackPanel>
</DataTemplate>
</ContextMenu.ItemTemplate>
</ContextMenu>
</TreeView.ContextMenu>
It looks like :
I want the ContextMenu to be like this:
The second problem:
Sometimes it works well but sometimes I get these strange things.
------------------------------Solved--------------------------------------------
For Sac1. I have modified your solution by adding x:Shared="False". Check MSDN for x:Shared.
<Style TargetType="MenuItem" x:Shared="False">
<Setter Property="Icon">
<Setter.Value>
<Image Source="{Binding Path=MyIcon}" Height="20" Width="20" >
</Image>
</Setter.Value>
</Setter>
<Setter Property="Header" Value="{Binding Path=Name}" />
<Setter Property="Command" Value="{Binding Command}" />
<Setter Property="CommandParameter" Value="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type TreeView}}, Path=DataContext.SelectedItem}" />
</Style>
For the wrong headers of menu items I had to override the method ToString() in MenuItemViewModel. I don't undestand why I had to override ToString() but it works well now.
public class MenuItemViewModel : BindableBase
{
......
public string Name
{
get
{
return model.Name;
}
set
{
this.model.Name = value;
OnPropertyChanged("Name");
}
}
public override string ToString()
{
return Name;
}
....
}
DataTemplate of MenuItem is not working as expected.
I used Style insted of DataTemplate:
<TreeView.Resources>
<Style TargetType="MenuItem">
<Setter Property="Icon" Value="{Binding MyIcon}" />
<Setter Property="Header" Value="{Binding Name}" />
<Setter Property="Command" Value="{Binding Command}" />
<Setter Property="CommandParameter" Value="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type TreeView}}, Path=DataContext.SelectedItem}" />
</Style>
</TreeView.Resources>
<TreeView.ContextMenu>
<ContextMenu ItemsSource="{Binding Path=SelectedItem.MenuItemsList}" />
</TreeView.ContextMenu>
You should not use a DataTemplate for the ContextMenu. Just use it as provided:
<ContextMenu>
<MenuItem Command="{Binding Path=Command}"
Icon="{Binding Path=MyIcon}"
Header="{Binding Path=Name}"
InputGetstureText="CTRL+O" />
</ContextMenu>
Dont use MenuItem in DataTemplate instead use button with BorderThickness="0" Background="Transparent"

WPF Grouped ListBox bound to CollectionView

I am trying to find a way to code a list of grouped users and be able to dynamically display their work that is assigned to them. I have an Observable Collection (UsersOC) that is bound to a CollectionViewSource in my XAML (Defined in the Resources section of the User Control) like so:
<CollectionViewSource x:Key="UserQueueList" Source="{Binding QueueList}">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="Name"></PropertyGroupDescription>
</CollectionViewSource.GroupDescriptions>
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="Name"/>
<scm:SortDescription PropertyName="EmployeeNumber"/>
<scm:SortDescription PropertyName="SortOrder"/>
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
So what I have is a list of all the users and their related work.
I have to represent every driver, with or without work, in a list (grouped by user name) and then their work. If they have no work I need to show a that says "Drop work here" which is a Drop zone which will add the work to their queue. I have to have the control be a ListBox under the driver name, so it will look like this:
--> Driver Name1
- work 1
- work 2
--> Driver Name2
Drop Work Here
--> Driver Name3
- work 1
- work 2
- work 3
the areas with the work items listed, again, are/should be list boxes and can be individually dragged and dropped (i have that portion of the code already). Here is what I have so far:
<ItemsControl ItemsSource="{Binding Source={StaticResource TrailerCardQueueList}}" Grid.ColumnSpan="2" Grid.Row="1" BorderBrush="Transparent"
Background="Transparent" Name="lvDriverQueueWork" Margin="10,0,10,0" Foreground="Black">
<ItemsControl.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<StackPanel>
<TextBlock FontSize="14" FontWeight="SemiBold">
<Run Text="{Binding Path=Items[0].EmployeeNumber}"/>
<Run Text="-"/>
<Run Text="{Binding Name, Mode=OneWay}"/>
</TextBlock>
</StackPanel>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ItemsControl.GroupStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<Grid>
<Grid.Style>
<Style TargetType="Grid">
<Style.Triggers>
//I figured I could hide/show the area here with the default drop zone if they have no work, but this doesn't work.
<DataTrigger Binding="{Binding Path=HasItems, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Value="False">
<Setter Property="Visibility" Value="Hidden"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
<TextBlock Grid.Row="0" Grid.Column="0" Text="DROP TRAILER CARD HERE"/>
</Grid>
<Grid>
<Grid.Style>
<Style TargetType="Grid">
<Style.Triggers>
<DataTrigger Binding="{Binding HasItems, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
<TextBlock Grid.Column="1" Text="{Binding , UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock Grid.Column="2" Text="{Binding , UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

Conditional formatting for the Header content

I have the following template for some header:
<telerik:RadExpander.Header>
<StackPanel Orientation="Horizontal" DataContext="{Binding CurrentItem, ElementName=activityProductGrid}">
<TextBlock Text="{Binding Strings[Product], Source={StaticResource LanguageResources}, StringFormat='{}{0}: '}" />
<TextBlock Text="{Binding Product.Name}" FontWeight="Bold" />
<TextBlock Text="{Binding Strings[GroupName], Source={StaticResource LanguageResources}, StringFormat=', {0}: '}" />
<TextBlock Text="{Binding GroupName}" />
<TextBlock Text="{Binding Strings[UnitPrice], Source={StaticResource LanguageResources}, StringFormat=', {0}: '}" />
<TextBlock Text="{Binding UnitPrice}" />
</StackPanel>
</telerik:RadExpander.Header>
How can I do conditional formmatting of the header, if for example Product == null, then Header should not display anything?
Edit: This one works.
<StackPanel Orientation="Horizontal" DataContext="{Binding CurrentItem, ElementName=activityProductGrid}">
<i:Interaction.Triggers>
<ie:DataTrigger Binding="{Binding}" Value="{x:Null}">
<ie:ChangePropertyAction TargetObject="{RelativeSource={RelativeSource AncestorType=StackPanel}}" PropertyName="Visibility">
<ie:ChangePropertyAction.Value>
<Visibility>Collapsed</Visibility>
</ie:ChangePropertyAction.Value>
</ie:ChangePropertyAction>
</ie:DataTrigger>
</i:Interaction.Triggers>
<-- from this point the came code as above -->
</StackPanel>
Specifically for null, you can specify binding parameters for a replacement value, or one to display in case of binding errors:
<TextBlock
Text="{Binding Product.Name, TargetNullValue=(empty), FallbackValue=(error)}"/>
(Taken from the WPF Binding Cheatsheet)
EDIT: I noticed that you didn't just want a specific binding to have a different value, but the whole control to not be displayed. For this, you can use Styles and Triggers, binging a DataTrigger to your Product property, and setting Visibility if it's null.
<telerik:RadExpander.Header>
<StackPanel>
<StackPanel.Style>
<Style TargetType="StackPanel">
<Style.Triggers>
<DataTrigger Binding="{Binding Product}" Value="{x:Null}">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
</StackPanel>
</telerik:RadExpander.Header>

Resources