DarioSantarelli.Blog(this);

Posts Tagged ‘WPF’

[WPF] From Visual to Bitmap

Posted by dariosantarelli on October 21, 2012


I’d like to share a couple of extension methods that helped me in situations where I needed to convert some rendered WPF windows or controls to bitmaps. Many devs know how complex this task was in Windows Forms. Instead, in WPF it’s quite simple, at least if you’re familiar with the RenderTargetBitmap class, and the range of BitmapEncoders. In order to convert a visual to a bitmap, I like to see something like this:

myVisual.ToBitmapSource().ToPngFile(@”C:\ScreenShot.png”);

The ToBitmapSource() extension method allows you to get a single, constant set of pixels at a certain size and resolution representing the visual (please note that a BitmapSource uses automatic codec discovery, based on the installed codecs on the user’s system). I’ve always found useful to replace the default black background that WPF reserves for transparency with a custom brush. So I introduced the transparentBackground parameter (default: white) which overrides the default black one.

public static BitmapSource ToBitmapSource(this Visual visual, Brush transparentBackground)
{
  var bounds = VisualTreeHelper.GetDescendantBounds(visual);
  var bitmapSource = new RenderTargetBitmap((Int32)bounds.Width, (Int32)bounds.Height, 96, 96, PixelFormats.Pbgra32);
  var drawingVisual = new DrawingVisual(); 
  using (var drawingContext = drawingVisual.RenderOpen())
  {
    var visualBrush = new VisualBrush(visual);
    drawingContext.DrawRectangle(transparentBackground, null, new Rect(new Point(), bounds.Size));
    drawingContext.DrawRectangle(visualBrush, null, new Rect(new Point(), bounds.Size));
  }

  bitmapSource.Render(drawingVisual);
  return bitmapSource;
}

public static BitmapSource ToBitmapSource(this Visual visual)
{
  return visual.ToBitmapSource(Brushes.White);
}

public static void ToPngFile(this BitmapSource bitmapSource, string fileName)
{
  var encoder = new PngBitmapEncoder();
  encoder.Frames.Add(BitmapFrame.Create(bitmapSource));
  using (var file = File.Create(fileName)) encoder.Save(file);
}

Posted in .NET Framework, C#, Microsoft Technology, WPF | Tagged: , | 1 Comment »

[WPF] Binding multiple command parameters using MultiBinding

Posted by dariosantarelli on November 7, 2010


In this post, I’d like to show how we can pass multiple values into an ICommand implementation by using the CommandParameter property of an input control. This is useful especially in MVVM architectures, so that the View can interact with the ViewModel in a clean way, facing the fact that the Execute method of the ICommand interface allows only a single object.
A solution is to use the MultiBinding class which allows us to define a collection of Binding objects attached to the target CommandParameter property of our input control. In a concrete example, let’s consider a simple search box with an OK button and a checkbox “ignore case”. The OK button is bound to a custom FindCommand defined in the ViewModel.
When the user clicks on the OK button, we want two parameters to be passed to the command: the string to be searched and the “ignorecase” option. How can we bind these two parameters to the Button’s CommandParameter?
Well, first we have to create a class to hold the parameters.

public class FindCommandParameters
{
  public string Text { get; set; }
  public bool IgnoreCase { get; set; }
}

After that, we have to create a class that implements the IMultiValueConverter interface. This simply converts our multiple parameters into the class that we have defined before.

public class FindCommandParametersConverter : IMultiValueConverter
{ 
  public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  {
    FindCommandParameters parameters = new FindCommandParameters(); 
    foreach (var obj in values)
    { 
       if (obj is string) parameters.Text = (string)obj;                
       else if (obj is bool) parameters.IgnoreCase = (bool)obj;
    } 
    return parameters;
  }
  public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
  {
    throw new NotImplementedException();
  }
}

As you can see in the code above, we can iterate through the list of input values of the Convert method, checking their type, and then correctly assign the properties of the parameter class. Obviously you can implement different solutions (you always know the order of the parameters set in the XAML), but the most important thing at this point is that the return value of the Convert method is what will be passed as argument to the Execute method of our FindCommand.
To wire up the XAML to take advantage of this class, we have to include the <Button.CommandParameter> element.  This contains the <MultiBinding> element, which has the “Converter” attribute. In the code below, the converter type is added as a resource to the button to make this post easier to read, but convention usually dictates resources are added at the Window level to allow reuse and readability.
Under the MultiBinding.Bindings element, we add a <Binding> element for each parameter that we need to pass into the command.

<TextBox x:Name="txtFind" />
<CheckBox x:Name="chkFindIgnoreCase" Content="Ignore case" />
 <Button Command="{Binding FindCommand}" Content="OK">
  <Button.Resources>
    <ui:FindCommandParametersConverter x:Key="findCommandParametersConverter" />
  </Button.Resources>
  <Button.CommandParameter>
    <MultiBinding Converter="{StaticResource findCommandParametersConverter}">
      <MultiBinding.Bindings>
        <Binding ElementName="txtFind" Path="Text" />
        <Binding ElementName="chkFindIgnoreCase" Path="IsChecked" />
      </MultiBinding.Bindings>
    </MultiBinding>
  </Button.CommandParameter>
</Button>

The final step is to consume the FindCommandParameters object instance in our FindCommand’s CanExecute and Execute methods.

Posted in WPF | Tagged: , , | 1 Comment »