65.9K
CodeProject is changing. Read more.
Home

WPF Attachment Control

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (3 votes)

Dec 15, 2009

CPOL

2 min read

viewsIcon

28257

downloadIcon

681

Attachment control using WPF.

Introduction

This control is a ListView control that holds a list of attachments, which has a link to the attachments and some metadata about them. This article demonstrates the basics of WPF controls and templating, including binding a list control to application data. The project includes the AttachmentList control which is a templated ListView, and a demo window which holds the application data and binds the data to the control.

Using the code

The control is made from a list box which holds the Attachment class that is defined by AttachmentTemplate that is set to the ListView ItemTemplate property.

<ListBox IsSynchronizedWithCurrentItem="True" 
         HorizontalAlignment="Stretch" 
         VerticalAlignment="Stretch" 
         x:Name="AttachmentListBox" 
         HorizontalContentAlignment="Stretch"
         SelectionChanged="AttachmentListBox_SelectionChanged"
         ItemTemplate="{DynamicResource AttachmentTemplate}"
         Margin="0,32,0,0"
         >

The control template is built from five rows, the attachment icon:

<Image x:Name="AttachmentIcon" 
    Source="\Images\attach.png" HorizontalAlignment="Left" />

and a text block for the title of the attachment:

<TextBlock x:Name="Title"
          Margin="16,0,0,0"
          Text="Title" HorizontalAlignment="Left"/>

The next block is the main data for the attachment which is separated into two columns: A text block which is multi-bound to UpdateUser and UpdateUserTime.

<TextBlock x:Name="CreationText" 
         Margin="0,0,0,0" 
         Grid.Column="0" 
         HorizontalAlignment="Left">
   <TextBlock.Text>
        <MultiBinding StringFormat="Edited by {0} on {1}">
           <Binding Path="UpdateUser"/>
           <Binding Path="UpdateDateTime"/>
        </MultiBinding>
   </TextBlock.Text>
</TextBlock>

And another text block which is multi-bound to UpdateUser and UpdateUserTime.

<TextBlock x:Name="UpdatingText" 
        Margin="2,0,0,0" Grid.Column="1" 
        HorizontalAlignment="Right">
  <TextBlock.Text>
    <MultiBinding StringFormat="Created by {0} on {1}">
      <Binding Path="CreationUser"/>
      <Binding Path="CreationDateTime"/>
    </MultiBinding>
  </TextBlock.Text>
</TextBlock>

The next row defines the file icon and the hyperlink to that file:

<Grid Grid.Row="2" >
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="Auto"/>
    <ColumnDefinition Width="*"/>
  </Grid.ColumnDefinitions>
  <Image x:Name="FileIcon" Source="/Images/File.png"
  Grid.Column="0" HorizontalAlignment="Left"/>
  <TextBlock x:Name="FilePath" Margin="2,0,0,0" Grid.Column="1">
    <Hyperlink NavigateUri="{Binding Path=FilePath}" 
              Hyperlink.RequestNavigate="Hyperlink_RequestNavigate">
      <TextBlock Text="{Binding Path=FileName}"/>
    </Hyperlink>
  </TextBlock>
</Grid>

A thing to mention here is the Hyperlink.RequestNavigate event, which is called upon pressing the hyperlink. You have to implement this event if you want the hyperlink to operate as you need it; otherwise, it does nothing. In our case, I implemented it by using System.Diagnostics.Process.Start in the code-behind, as follows:

System.Diagnostics.Process.Start(e.Uri.ToString());

Simple, once you know this. The last text block is for the description of the attachment, which is a simple text block. Next, we have the control toolbar which defines two actions: add attachment and delete attachment.

<ToolBar Height="32" x:Name="AttachmentsToolbar" VerticalAlignment="Top">
  <Button x:Name="AddAttachment" Command="{Binding Controller.AddAttachmentCommand}">
    <Image Source = "/Images/attach.png"/>
  </Button>
  <Button x:Name="DeleteAttachment" 
            Command="{Binding Controller.DeleteAttachmentCommand}">
    <Image Source = "/Images/delete32.png"/>
  </Button>
</ToolBar>

Notice that the command for the actions is binding, which is done by using a DelegateCommand which is defined in Prism. The delegate command is attached in the project so you don't need to worry about this part. A DelegateCommand is an easy way of implementing Commands in your application. For further information, follow this link: http://development-guides.silverbaylabs.org/Video/Prism-Commands.

And... I think that's about it. The code-behind is straightforward... so I didn't go in to much detail there. I am waiting for your comments...