Running on Empty

The few things I know, I like to share.

Model-View-ViewModel (MVVM) – Part 1

I have been working with MVVM for about a year now as part of work related projects. For the larger portion of my career I have focused on Model View Controller or Model View Presenter schemas for user interface. However, after learning as much as possible about MVVM from experts around the web, I have adopted it as my primary method UI implementation.

So what is MVVM? For the most part it is MVC on steroids, it is a way to split presentation design from codified logic specific to the application. In WPF, it allows easy access to core features such as databinding. It allows the developer to write UI seperately from business logic, which seperates the visible behavior from the logical behavior of the application. A nice side effect is unit testing of the application becomes much easier, since most if not all application logic is handled as methods. It is easier to describe in parts:

ViewModel - is the entity(ies) that the application is trying to manage and consume

  • This is your entity class, everything here should be Properties.

View-Model – is an intermediary layer where most of the logic live for specific business applications.

  • This layer is not aware of UI controls.
  • Here you expose Public properties that the UI layer will be bound.
  • Use public methods invoked by events/commands
  • Update the View through databinding
  • Update the Model through bound properties

View  – is how the View-Model is displayed, the UI.

  • Contains the XAML in a WPF application
  • Command bindings – routed commands
  • Property bindings
  • Code behind should be as clean as possible
  • Should include basic wiring to instantiate the view
  • General Rule of Thumb – if you have x:Name in your XAML, you are doing it wrong.

In the next article I will demonstrate the view model base class.

July 22, 2011 Posted by | C#, MVVM, TDD, WPF, XAML | Leave a comment

WPF ProgressBar and Long Running Processes

Introduction

Often during long running processes it is useful to indicate in the UI that the process is running.  Rather than simply locking the UI from the user it is preferable to display a progressbar.  In my current implementation I have a server side process that I know takes a maximum of 30 seconds to complete.  So when I call this process from the UI, I display a progressbar that is timed to reach it’s maximum at 30 seconds.

The ProgressBar Window

<Windown ...>
 

      <ProgressBar x:Name="MessageProgessBar"
                   Maximum="100" Minimum="0"
                   Height="25" Width="275">
        <ProgressBar.Triggers>
          <EventTrigger RoutedEvent="ProgressBar.Loaded">
            <BeginStoryboard>
              <Storyboard>
                <DoubleAnimation Storyboard.TargetName="MessageProgessBar"
                                 Storyboard.TargetProperty="Value"
                                 From="0" To="100" Duration="0:0:30"/>
              </Storyboard>
            </BeginStoryboard>
          </EventTrigger>
        </ProgressBar.Triggers>
      </ProgressBar>
    </StackPanel>
  </Border>
</Window>

Calling Long Running Processes

//Open the Progressbar Window.
ThreadStart ts = delegate
{
 // DO LONG RUNNING PROCESS HERE!
 Dispatcher.BeginInvoke(DispatcherPriority.Normal, (EventHandler)
        delegate
        {
         // Do Cleanup Process HERE!               
        }, null, null);
};
ts.BeginInvoke(null, null);

Thank you Linda for your comments and reminder of subjects I have yet to post.

Please feel free to leave comments or suggestions.

January 23, 2009 Posted by | C#, WPF, XAML | 4 Comments

Using FlowDocuments XAML to print XPS Documents. (Part 6)

Indroduction

This one is for you Linda and Cow-Killer.

Welcome to Part 6 of the Using FlowDocuments XAML to print XPS Documents series.  Up until now it has been impossible to use this series to create an XPS document file or display the XAML text in a document viewer.  It would be nice to be able to create a XAML template and easily insert text into the template using databinding.  Here is my solution, hope to hear your feedback.

Creating a new method to Load Xaml Strings

This method simply takes a raw XAML string and loads it into a FlowDocument, you may have seen this before in previous samples.

        public static IDocumentPaginatorSource RenderFlowDocumentTemplate(string templatePath, 

Dictionary<string, string> parameters)
        {
            string rawXamlText = "";
            using (StreamReader streamReader = File.OpenText(templatePath))
            {
                rawXamlText = streamReader.ReadToEnd();
            }

            rawXamlText = MergeParameters(parameters, rawXamlText);

            FlowDocument document = XamlReader.Load(new XmlTextReader(new StringReader(rawXamlText))) as 

FlowDocument;
           
            return document;
        }

The new parts of this method are the addition of a Dictionary of string key/value pairs and the MergeParameters method.

Merging Parameters

Since XAML is nothing more than a jazzed up XML file, we can use simple string replacements to replace items in our template with strings from our objects.

        private static string MergeParameters(Dictionary<string, string> parameters, string template)
        {
            foreach (KeyValuePair<string, string> kvp in parameters)
            {
                template = template.Replace(string.Format("[{0}]", kvp.Key), kvp.Value);
            }
            return template;
        }

Now we have a nearly completed solution to XAML template rendering, all that is left to do is create a template.

The new XAML Template

<FlowDocument xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
     xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml>
    <Paragraph FontFamily="Arial" Margin="20">
        <TextBlock Text="[TestString]" FontSize="12"/>
    </Paragraph>
</FlowDocument>

Notice the inclusion of [TestString], this is essentially the “databind” we will use in the string Key/Value pair dictionary.

Using the new Key/Value pair databinding

            Dictionary<string, string> strings = new Dictionary<string,string>();
            strings.Add("TestString", "Tester");
            IDocumentPaginatorSource flowDocument =
                

XamlTemplatePrinter.RenderFlowDocumentTemplate(Path.Combine(Environment.CurrentDirectory, 

"TestTemplate.xaml"), strings);
            flowDocument.DocumentPaginator.PageSize = new Size(96 * 8.5, 96 * 11);
            PrintDialog flowPrintDialog = XamlTemplatePrinter.GetPrintDialog();
            if (flowPrintDialog == null)
                return;
            PrintQueue flowPrintQueue = flowPrintDialog.PrintQueue;
            XamlTemplatePrinter.PrintFlowDocument(flowPrintQueue, 

flowDocument.DocumentPaginator);

Conclusion

Thank you all for your comments and suggestions.  Your questions and comments are fuel for the continued success of this blog.  Please feel free to leave a comment or contact me if you have suggestions or questions.

May 28, 2008 Posted by | C#, WPF, XAML, XPS | 15 Comments

Using FlowDocuments XAML to print XPS Documents. (Part 5)

Introduction

Welcome to Part 5 of the Using FlowDocument XAML to print XPS Documents series.  This article has been a long time coming.  In this article I will focus on creating dynamic XAML content.

Creating a method to Load Xaml Strings

This method simply takes a raw XAML string and loads it into a FlowDocument.

        public static IDocumentPaginatorSource RenderFlowDocumentString(string rawXamlString, object dataContextObject)
        {
            FlowDocument document = XamlReader.Load(new XmlTextReader(new StringReader(rawXamlString))) as FlowDocument;
            if (dataContextObject != null)
            {
                document.DataContext = dataContextObject;
            }
            return document;
        }

Now all we need to do is create some XAML strings.

Using the new Xaml string loader plus some.

        public void PrintGenericList(List<Awards> awardList)
        {
            PrintDialog flowPrintDialog = XamlTemplatePrinter.GetPrintDialog();
            if (flowPrintDialog == null)
                return;


                StringBuilder xamlString = new StringBuilder();
                
                xamlString.Append("<FlowDocument xmlns=\"<a href="http://schemas.microsoft.com/winfx/2006/xaml/presentation\">http://schemas.microsoft.com/winfx/2006/xaml/presentation\</a>" \nxmlns:x=\"<a href="http://schemas.microsoft.com/winfx/2006/xaml\">http://schemas.microsoft.com/winfx/2006/xaml\</a>">");
                
                foreach (Awards award in awardList)
                {
                    xamlString.Append("<Paragraph FontFamily=\"Arial\" Margin=\"20\">");
                    xamlString.AppendFormat("<TextBlock Text=\"{0}  {1}\" Margin=\"170,0,0,0\" />", award.SerialNumber, award.ControlNumber);
                    xamlString.Append("<TextBlock Text=\"\" Margin=\"170,0,0,0\" />");
                    xamlString.Append("</Paragraph>");
                }

                xamlString.Append("</FlowDocument>");

                IDocumentPaginatorSource flowDocument =
                       XamlTemplatePrinter.RenderFlowDocumentString(xamlString.ToString(), null);

                flowDocument.DocumentPaginator.PageSize = new Size(96 * 5, 96 * 2);

                PrintQueue flowPrintQueue = flowPrintDialog.PrintQueue;
                XamlTemplatePrinter.PrintFlowDocument(flowPrintQueue, flowDocument.DocumentPaginator);            
        }

Conclusion

In this article I demonstrated building dynamic XAML to print or same as an XPS document.  I am personally using this in an application to format labels to be sent to a printer.

April 30, 2008 Posted by | C#, WPF, XAML, XPS | 4 Comments

WPF EnumComboBox UserControl

Introduction

In this article I will demonstrate a custom control that will allow you to display items from an enum in a combo box.  I have a couple of requirements though.

  • The displayed values must be in human readable strings, numbers or the enum type would not do.
  • The implementation must be easily reusable.

Creating the EnumComboBox Control

First, create a class that will allow us to view the description of custom attributes.

public class EnumerateUtil
{
    // Methods
    private EnumerateUtil()
    {
    }

    public static string GetDescription(Enum value)
    {
        DescriptionAttribute[] customAttributes = (DescriptionAttribute[]) value.GetType().GetField(value.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false);
        return ((customAttributes.Length > 0) ? customAttributes[0].Description : value.ToString());
    }
}

Next, create a new custom control, I called mine EnumComboBox.

public class EnumComboBox : System.Windows.Controls.ComboBox
{
    static EnumComboBox()
    {
       
        //This OverrideMetadata call tells the system that this element wants to provide a style that is different than its base class.
        //This style is defined in themes\generic.xaml
        //DefaultStyleKeyProperty.OverrideMetadata(typeof(EnumComboBox), new FrameworkPropertyMetadata(typeof(EnumComboBox)));
    }

    protected override void OnInitialized(EventArgs e)
    {
        base.OnInitialized(e);
        FillItems();       
    }

    private string _enumType;
    [Browsable(true), Category("Data"), Description("Sets the fully qualified type of the enum to display in the DropDownList")]
    public string EnumTypeName
    {
        get { return _enumType; }
        set { _enumType = value; }
    }

    private List<KeyValuePair<int, string>> CachedValues
    {
        get
        {
            if (App.Current != null && App.Current.Properties != null)
            {
                return (List<KeyValuePair<int, string>>)App.Current.Properties["EnumComboBox_" + EnumTypeName];
            }
            else
            {
                return null;
            }
        }
        set
        {
            if (App.Current != null && App.Current.Properties != null)
            {
                App.Current.Properties["EnumComboBox_" + EnumTypeName] = value;
            }
        }
    }

    private void FillItems()
    {
        List<KeyValuePair<int, string>> values = CachedValues;
        if (values == null)
        {
            values = new List<KeyValuePair<int, string>>();
            Type enumType = Type.GetType(EnumTypeName);
            if (enumType == null)
            {
                throw new ArgumentException("Cannot load the type: " + EnumTypeName);
            }
            Array enumValues = Enum.GetValues(enumType);
            for (int index = 0; index < enumValues.Length; index++)
            {
                int value = (int)enumValues.GetValue(index);
                Enum enumValue = (Enum)enumValues.GetValue(index);
                values.Add(new KeyValuePair<int, string>(value, EnumerateUtil.GetDescription(enumValue)));
            }
            CachedValues = values;
        }

        this.ItemsSource = values;
        this.DisplayMemberPath = "Value";
        this.SelectedValuePath = "Key";
    }
}

Note, I commented the OverrideMetadata style property in the constructor.  This is because, I want to apply my template on a control by control basis.Finally, create your enum and use description attributes to specify the visible string.

public enum TestType
{
    [Description("Object One"), EnumMember]
    ObjectOne = 1
   ,
    [Description("Object Two"), EnumMember]
    ObjectTwo = 2
}

 


Declaring the EnumComboBox

Now all we need to do is point the EnumTypeName property to the Entity that we will use to fill the combo box values.

<customControls:EnumComboBox EnumTypeName="YourNamespace.TestType, YourNamespace"/>

 


Conclusion

In this article I demonstrated using Description attributes and custom controls to create a combobox that will fill with human readable strings.  Hopefully you found this useful.

Please feel free to leave comments or suggestions.

January 15, 2008 Posted by | C#, WPF, XAML | 3 Comments

Creating more responsive WPF UI via Multi-Threading.

Introduction

In this article I will demonstrate a multi-threading technique to make WPF UI more response on long database or process calls.  A few things we want to keep in mind:

  • Never ever use the UI thread to make a long process call.
  • Display to the user that a long process is taking place, so the user doesn’t think your application is broken.
  • Always synch the process thread back to the UI thread after the long process call.

With these things in mind, our WPF applications will become more responsive and friendly to users.

Creating user friendly WPF.

One very clean way to display to the user that a control has items that are being refreshed on a long process is to grey it out.  I started off by disableing all the controls in the section that was being refreshed, but that simply looked ugly to me.  So instead, I tossed up a transparant rectangle instead.  This immediately gave me two benefits:

  • I no longer had to keep track of individual controls or panels to disable/enable.
  • I had much more control over the look and feel of the application, brought the sexiness back.

So this is what I have been doing, first I add a style to AppStyles.xaml.  You might recognize this from a few of my other articles, I always reuse code whenever possible.

  <Style x:Key="UserControlOverlayRectangleStyle" TargetType="{x:Type Rectangle}">
    <Setter Property="Fill" Value="#FF151515"/>
    <Setter Property="Opacity" Value="0.61"/>
  </Style>

Now, add a rectangle to your Grid/Panel/Canvas, whatever.  Notice the Rectangle is Visibility.Collapsed

<Grid>
  <!-- ListView or some other controls that I want
       to hide during the long refresh go here -->
  <Rectangle Name="ProcessingRectangle" Margin="0,0,0,0" Style="{DynamicResource UserControlOverlayRectangleStyle}" Visibility="Collapsed"/>
</Grid>

   
Multi-Threaded goodness

Create the following in your code behind.

private void PopulateControlsDuringLongRefreshCall()
{
    //Show processing
    ShowProcessing();

    ThreadStart ts = delegate
    {
        // Do long work here

        Dispatcher.BeginInvoke(DispatcherPriority.Normal, (EventHandler)
        delegate
        {
            HideProcessing();
        }, null, null);
    };
    ts.BeginInvoke(delegate(IAsyncResult aysncResult) { ts.EndInvoke(aysncResult); }, null);
}

private void ShowProcessing()
{
    ProcessingRectangle.Visibility = Visibility.Visible;
}

private void HideProcessing()
{
    ProcessingRectangle.Visibility = Visibility.Collapsed;
}

 


Conclusion

In this article I demonstrated how to use a multithreading technique to make the WPF UI more responsive during long database or processing calls.  Hopefully, you will find this useful, I have used this technique in other areas besides WPF.

Your comments and suggestions are always welcome.  Your feedback is very helpful in keeping articles up to date.

January 11, 2008 Posted by | C#, WPF, XAML | 1 Comment

WPF UserControls as a Modal-like Dialog.

Introduction

This article is in direct response to feedback from the WPF Popup Controls series.  What if you needed a User Control to “popup” as a Windows Dialog, have all the properties of a Windows Dialog, but behave as a Popup Control.

Creating a UserControl…plus a little something extra.

Create a WPF User Control as you would normally, but you will want to make certain you put at least one button on the UserControl.

<Button x:Name="CancelButton" Content="Cancel" Click="CancelButton_Click" Width="120" Height="50"/>

Now include a RoutedEvent using the Bubble RoutingStrategy for the button you just created.  This will allow any Page or Window that implements this control to intercept the ClickEvent.Place a couple of Methods that will Show and Hide the user control.  You could also create Dependency Properties at this point to pass Properties between the Parent and the UserControl, not shown here though.

namespace TestCase.UserControls
{
    public partial class TestControl : UserControl
    {
        #region Events

        private void CancelButton_Click(object sender, RoutedEventArgs e)
        {
            RaiseEvent(new RoutedEventArgs(CancelButtonClickEvent));
        }

        #endregion

        #region RoutedEvents

        public static readonly RoutedEvent CancelButtonClickEvent = EventManager.RegisterRoutedEvent(
            "CancelButtonClick", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TestControl));
        public event RoutedEventHandler CancelButtonClick
        {
            add { AddHandler(CancelButtonClickEvent, value); }
            remove { RemoveHandler(CancelButtonClickEvent, value); }
        }
      
        #endregion

        public TestControl()
        {
            InitializeComponent();
        }

        public void Show()
        {
            Visibility = Visibility.Visible;
        }

        public void Hide()
        {
            Visibility = Visibility.Collapsed;
        }
    }
}

Using the UserControl.

You will now need to declare the user control on a Window or Page.  This means the Page or Window Header needs to declare the namespace for your UserControl.

xmlns:UserControls="clr-namespace:TestCase.UserControls"

Now finally we are ready to declare our user control.

<UserControls:TestControl HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Stretch"
                          Width="Auto" Height="Auto" Visibility="Collapsed"
                          x:Name="TestUserControl"
                          CancelButtonClick="TestUserControl_CancelButtonClick" />

Notice the control Visiblilty property is set to Collapsed.  We now need to write the code behind, our main focus will be to display and hide the user control.

private void TestUserControl_CancelButtonClick(object sender, RoutedEventArgs e)
{
    HideTestUserControl();
}

private void ShowTestUserControl()
{
    TestUserControl.Show();
}

private void HideTestUserControl()
{
    TestUserControl.Hide();
}

On the main parent Page or Window, simply wire up a Button click or some other user Event and call ShowTestUserControl().

Making it look Pretty.

You will most likely want to make the background control grey out to indicate focus is now on your User Control as well as steal focus from the Parent Window while the user control is active.  This can easily be accomplished using a rectangle.

Add the following code to your AppStyles.xaml

  <Style x:Key="UserControlOverlayRectangleStyle" TargetType="{x:Type Rectangle}">
    <Setter Property="Fill" Value="#FF151515"/>
    <Setter Property="Opacity" Value="0.61"/>
  </Style>

Also add the following code to your UserControl.

<Grid Opacity="1" Width="Auto" Height="Auto" Background="{x:Null}">
     <Rectangle Name="MainRectangle" Margin="0,0,0,0" Style="{DynamicResource UserControlOverlayRectangleStyle}"/>
     <!-- Everything Else -->
</Grid>

Conclusion

We now have a simple way to add declare user controls on a Page or Window and have them behave as Dialog Windows. 

Please feel free to leave suggestions or comments.  I look forward to your feedback.

January 10, 2008 Posted by | C#, WPF, XAML | 12 Comments

WPF Popup control. (Part 2, User controls as Popups)

Introduction

In Part 1 of this series I outlined a way of creating a Popup control using WPF.  In this article I will demonstrate creating a Popup using Dependency Properties, not quite so quick, but much more elegant.  The main benefit of creating user controls is reusability.

Creating a Popup User Control.

public class PopupTest : System.Windows.Controls.Control
{
    Popup _parentPopup;
    /// <summary>
    /// Constructor
    /// </summary>
    public PopupTest()
        : base()
    {
    }
 
    static PopupTest()
    {
        //This OverrideMetadata call tells the system that this element wants to provide a style that is different than its base class.
        //This style is defined in themes\generic.xaml
        DefaultStyleKeyProperty.OverrideMetadata(typeof(PopupTest), new FrameworkPropertyMetadata(typeof(PopupTest)));
    }
}

This is pretty much the template class for a user control with one small addition, the property Popup.  Note the visual style for the control will appear in Generic.xaml.

Adding Dependency Properties to add Popup Functionality.

Basically you have a shell for a User Control at this point.  All you need to add are some dependency properties to add Popup functionality to the control.

#region Properties
public bool IsOpen
{
    get { return (bool)GetValue(IsOpenProperty); }
    set { SetValue(IsOpenProperty, value); }
}

public bool StaysOpen
{
    get { return (bool)GetValue(StaysOpenProperty); }
    set { SetValue(StaysOpenProperty, value); }
}
#endregion
#region DependencyProperties
//Placement
public static readonly DependencyProperty PlacementProperty =
            Popup.PlacementProperty.AddOwner(typeof(PopupTest));
public PlacementMode Placement
{
    get { return (PlacementMode)GetValue(PlacementProperty); }
    set { SetValue(PlacementProperty, value); }
}
//PlacementTarget
public static readonly DependencyProperty PlacementTargetProperty =
            Popup.PlacementTargetProperty.AddOwner(typeof(PopupTest));
public UIElement PlacementTarget
{
    get { return (UIElement)GetValue(PlacementTargetProperty); }
    set { SetValue(PlacementTargetProperty, value); }
}
//PlacementRectangle
public static readonly DependencyProperty PlacementRectangleProperty =
            Popup.PlacementRectangleProperty.AddOwner(typeof(PopupTest));
public Rect PlacementRectangle
{
    get { return (Rect)GetValue(PlacementRectangleProperty); }
    set { SetValue(PlacementRectangleProperty, value); }
}
//HorizontalOffset
public static readonly DependencyProperty HorizontalOffsetProperty =
            Popup.HorizontalOffsetProperty.AddOwner(typeof(PopupTest));
public double HorizontalOffset
{
    get { return (double)GetValue(HorizontalOffsetProperty); }
    set { SetValue(HorizontalOffsetProperty, value); }
}
//VerticalOffset
public static readonly DependencyProperty VerticalOffsetProperty =
            Popup.VerticalOffsetProperty.AddOwner(typeof(PopupTest));
public double VerticalOffset
{
    get { return (double)GetValue(VerticalOffsetProperty); }
    set { SetValue(VerticalOffsetProperty, value); }
}
public static readonly DependencyProperty StaysOpenProperty =
Popup.StaysOpenProperty.AddOwner(
        typeof(PopupTest),
        new FrameworkPropertyMetadata(
                false,
                FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                new PropertyChangedCallback(OnStaysOpenChanged)));
public static readonly DependencyProperty IsOpenProperty =
 Popup.IsOpenProperty.AddOwner(
         typeof(PopupTest),
         new FrameworkPropertyMetadata(
                 false,
                 FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                 new PropertyChangedCallback(OnIsOpenChanged)));
#endregion

Now add some event handlers for the PropertyChangedCallback events.

private static void OnStaysOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    PopupTest ctrl = (PopupTest)d;
 
    if ((bool)e.NewValue)
    {
        ctrl.StaysOpenParentPopop((bool)e.NewValue);
    }
}
private static void OnIsOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    TenKeyPopup ctrl = (TenKeyPopup)d;
    if ((bool)e.NewValue)
    {
        if (ctrl._parentPopup == null)
        {
            ctrl.HookupParentPopup();
        }
    }
}
private void StaysOpenParentPopop(bool newValue)
{
    _parentPopup.StaysOpen = newValue;
}
private void HookupParentPopup()
{
    _parentPopup = new Popup();
    _parentPopup.AllowsTransparency = true;
    Popup.CreateRootPopup(_parentPopup, this);
}

Conclusion

This method of creating Popup controls is a little bit more difficult than the quick and dirty method described in Part 1.  However, we can now benefit from reusability and encapsulation of the control.  We could easily add dependency properties at this point to add functionality to the control as well as visual styles.

Actually using the Popup control is the same as what is describe in Part 1.  Please feel free to leave comments and suggestions.

January 8, 2008 Posted by | C#, WPF, XAML | 13 Comments

WPF Popup control. (Part 1, the Quick and Dirty Way)

Introduction

One of my favorite features in WPF is the separation of functionality and display of visuals in the UI.  So I thought I would start a new series demonstrating some cool features I have used in WPF, starting with Popup controls.

Declaring a Popup control, the Quick and Dirty way.

The quickest and easiest way to create a pop up control is to declare the Popup in XAML.  I chose to use a Viewbox in this example to make sizing a little easier.  The following code can be added to any Panel or Canvas.

<Popup x:Name="PopupTest" AllowsTransparency="True">
    <Viewbox VerticalAlignment="Top">
        <TextBlock Text="Wow, that was easy!"/>
    </Viewbox>
</Popup>

Showing the Popup control.

Now create an event handler based on an action in your window.  I chose the MouseEnter event in this sample.The main parameters that need to be set here are Placement, StaysOpen and IsOpen.  Placement sets where the Popup will actually be placed, PlacementMode.Mouse is most likely what you want.  StaysOpen determines if the Popup will close if it loses focus.  Finally, IsOpen will make the Popup visible.

void Window_MouseEnter(object sender, MouseEventArgs e)
{
    PopupTest.Placement = System.Windows.Controls.Primitives.PlacementMode.Mouse;
    PopupTest.StaysOpen = false;
    PopupTest.Height = 1000;
    PopupTest.Width = 500;
    PopupTest.IsOpen = true;
}

Conclusion

Like I said, quick and dirty.  This method of Popups probably should be used any time you want a Popup that doesn’t need to be replicated throughout your application and doesn’t require dependency properties.  In future articles of this series I will demonstrate using some more complex Popup controls. 

I look forward to your comments and suggestions.  Please feel free to request future articles.

January 7, 2008 Posted by | C#, WPF, XAML | 8 Comments

Using FlowDocuments XAML to print XPS Documents. (Part 4)

Introduction

Welcome to Part 4 of the Using FlowDocument XAML to print XPS Documents series. This article will focus on saving XAML to an XPS Document file… finally.

In previous parts of this series I demonstrated creating DocumentPaginator, adjusting PageSize, and printing.  Saving the XPS document is actually quite easy at this point. I will be building upon the classes discussed in Part 1, 2 and 3 of this series.

Creating a method to save an XPS document from a DocumentPaginator.

This method accepts a DocumentPaginator source and saves it to test.xps file, clean and simple.  Obvious improvments would be to use a save file dialogue.

public static void CreateXPSDocument(DocumentPaginator paginator)
{
    using (Package container = Package.Open("test" + ".xps", FileMode.Create))
    {
        using (XpsDocument xpsDoc = new XpsDocument(container, CompressionOption.Maximum))
        {
            XpsSerializationManager xpsSM = new XpsSerializationManager(new XpsPackagingPolicy(xpsDoc), false);
            xpsSM.SaveAsXaml(paginator);
        }
    }
}

Using the CreateXPSDocument method.

private void SaveXPSButton_Click(object sender, RoutedEventArgs e)
{
    SampleClass sample = new SampleClass();
    sample.Sample = "FlowDocument DataBinding Sample";   

    IDocumentPaginatorSource flowDocument =
        XamlTemplatePrinter.RenderFlowDocumentTemplate(Path.Combine(Environment.CurrentDirectory, "XamlDocumentTemplate.xaml"), sample);      

    flowDocument.DocumentPaginator.PageSize = new Size(96 * 8, 96 * 11);       

    XamlTemplatePrinter.CreateXPSDocument(flowDocument.DocumentPaginator);
}

Yes, it really was that easy. The XamlTemplatePrinter class we have created during this series is now actually becoming quite useful. This article will conclude this series for now, unless I think of something I might have forgotten.Please feel free to comment or leave suggestions for future articles.

January 4, 2008 Posted by | C#, WPF, XAML, XPS | 12 Comments

Follow

Get every new post delivered to your Inbox.