MSDN Magazine - December 2007 - (Page 61) IValueConverter. This is a common technique for performing custom conversion during data binding. The IValueConverter interface defines two methods, but I only care about one—Convert. The data-binding engine calls this method when it propagates a value from the binding source to the binding target. In my implementation, I simply use the CodeBase of the current assembly and prepend this as the path to the image file name. public class ImagePathConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { string path = Assembly.GetExecutingAssembly().CodeBase.Substring (“file:///”.Length); path = Path.GetDirectoryName(path) + “\\Images\\”; return string.Format(“{0}{1}”, path, (string)value); } } on the sizing of its children and passes this down, and each child in turn passes the information down to its children. This calls the ArrangeOverride method, where I can tell the children their size and lay them out. In my implementation of MeasureOverride, I use the UIElement.DesiredSize property to try to give the children all the space they need. In ArrangeOverride, I add scale transforms and Figure 3 Template for the Databound Button Controls Then, back in the FishEyeControl.xaml, I connect these pieces in a ResourceDictionary for the control and use the ResourceDictionary in the ItemsControl (see Figure 3). Note that the DataTemplate for the items within the panel is set to be a Button with an Image, and the Image uses the ImagePathConverter during data binding. This definition also specifies the buttonClick event handler for each Button. Although I could handle the event within the WPF control itself, as well as within the hosting Windows Forms control or the add-in, I’ll handle it only in the WPF control and the addin. I implement the event handlers in FishEyeControl.xaml.cs by extracting the button Image name and firing the event again. The VSTO add-in will react to the event by invoking the WCF service, based on the Image name (see Figure 4). Next I define a custom EventArgs type so that when I refire the event I can send the simple name of the button Image out to the listener as shown in the following, public delegate void FishEyeEvent(object source, FishEyeEventArgs e); public class FishEyeEventArgs : EventArgs { public String ButtonName; public FishEyeEventArgs(String name) { ButtonName = name; } Figure 4 Handling the FishEye Click Event public partial class FishEyeControl : System.Windows.Controls.UserControl { public event FishEyeEvent FishEyeClickEvent; private void buttonClick(object sender, RoutedEventArgs e) { Button buttonSender = (Button)sender; Image buttonImage = (Image)buttonSender.Content; ImageSource imageSource = buttonImage.Source; String imageName = imageSource.ToString(); int lastSlash = imageName.LastIndexOf(‘/’) + 1; String buttonName = imageName.Substring( lastSlash, imageName.Length - lastSlash - “.jpg”.Length); FishEyeEventArgs fe = new FishEyeEventArgs(buttonName); if (FishEyeClickEvent != null) { FishEyeClickEvent(sender, fe); } } Recall that I’m invalidating the FishEyePanel when the user moves the mouse over it. I also want to control how the rendering behaves so that I can provide the fish-eye animation behavior. To take control of rendering, I must implement two overrides, MeasureOverride and LayoutOverride, which implement a twopass layout system. During the measurement pass, the parent (FishEyeControl) calls the child (FishEyePanel) to find out how much space the child needs. The standard behavior here is for the child control to query its own children to find out how much space they need and then pass the result back up to the parent. WPF uses a model where controls can be nested almost indefinitely, so in this context, the entire tree is queried for its space requirements and the information is passed back up to the ultimate parent. In the layout pass, a similar recursion takes place, where the parent decides } } Office Services december2007 61
For optimal viewing of this digital publication, please enable JavaScript and then refresh the page. If you would like to try to load the digital publication without using Flash Player detection, please click here.