So they want a paper clip displayed at the top level, if any of the payments within that row have attachments. They want the paperclip to have a tooltip with clickable links. I explained that's not a viable solution because the tooltip will close as soon as they move the mouse towards it.
I suggested a context sensitive menu, but I was unsure whether I could generate one on the fly (there are different attachments to be displayed for each top level row) and I was also unsure if I could format it nicely (it's just a menu).
I saw the MenuItem.Header property is an object so I should be able to construct some kind of panel and use that as the header. Maybe I can also leverage the ContextMenu.Opened event to regenerate the context menu's contents on the fly.
Here's a greatly simplified solution with just a list of payments and a context sensitive menu listing their attachments.
<Window x:Class="ClickableTooltip.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ClickableTooltip"
mc:Ignorable="d"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<RoutedCommand x:Key="OpenAttachment"/>
</Window.Resources>
<Window.CommandBindings>
<CommandBinding Command="{StaticResource OpenAttachment}" Executed="CommandBinding_Executed"/>
</Window.CommandBindings>
<DataGrid ItemsSource="{Binding Payments}" IsReadOnly="True" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Image Source="paperclip.jpg" Height="20">
<Image.ContextMenu>
<ContextMenu Opened="ContextMenu_Opened"/>
</Image.ContextMenu>
</Image>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Binding="{Binding}"/>
</DataGrid.Columns>
</DataGrid>
</Window>
I got paperclip.jpg from Google Images. Feel free to choose your own. The jpg file is in the root of the project.
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace ClickableTooltip
{
public partial class MainWindow : Window, INotifyPropertyChanged
{
public class cAttachment
{
public string
PaymentNumber { get; set; }
public string
AttachmentName { get; set; }
public string Creator
{ get; set; }
}
public List<cAttachment> Attachments
{
get
{
return new
List<cAttachment>()
{
new cAttachment() {AttachmentName ="County guidelines", Creator="rsnipper",
PaymentNumber="123456"},
new cAttachment() {AttachmentName="Vendor contract", Creator="abaglady", PaymentNumber="123478"},
new cAttachment() {AttachmentName="A ridiculously long attachment name that goes on
forever", Creator="rsmith",
PaymentNumber="123478" }
};
}
}
public List<string>
Payments
{
get
{
return Attachments.Select(a => a.PaymentNumber).Distinct().ToList();
}
}
public MainWindow()
{
InitializeComponent();
}
private void
ContextMenu_Opened(object sender,
RoutedEventArgs e)
{
ContextMenu cm = sender as ContextMenu;
RoutedCommand oa = this.FindResource("OpenAttachment") as RoutedCommand;
cm.Items.Clear();
foreach (cAttachment a in Attachments.Where(a =>
a.PaymentNumber==cm.DataContext.ToString()))
{
MenuItem mi = new MenuItem();
StackPanel sp = new StackPanel() { Orientation =
Orientation.Horizontal };
sp.Children.Add(new TextBlock() { Text =
a.PaymentNumber, Width = 60 });
sp.Children.Add(new TextBlock() { Text =
a.AttachmentName, TextTrimming=TextTrimming.CharacterEllipsis, Width = 150 });
sp.Children.Add(new TextBlock() { Text = a.Creator });
mi.Header = sp;
mi.Command = oa;
mi.CommandParameter =
a.AttachmentName;
mi.CommandTarget =
cm.PlacementTarget;
cm.Items.Add(mi);
}
}
private void
CommandBinding_Executed(object sender,
ExecutedRoutedEventArgs e)
{
MessageBox.Show(string.Format("Here is attachment '{0}'", e.Parameter), "Hi");
}
public event
PropertyChangedEventHandler PropertyChanged;
public void
PropChanged(string name)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
}
The result looks like this.
No comments:
Post a Comment