Visualizzazione post con etichetta MVVM. Mostra tutti i post
Visualizzazione post con etichetta MVVM. Mostra tutti i post

giovedì 4 settembre 2014

Set the DecodePixelHeight property (Binding) of the BitmapImage object from the configuration file

C# .NET Framework 4.0 (WPF - MVVM)

In my MVVM WPF application, I want to resize a bitmap image with values stored in app.config. Therefore, for doing this I’ve tried to bind the Image.Height property and the BitmapImage.DecodePixelHeight directly to my ViewModel, like in this way:

In app.config

<?xml version="1.0" encoding="utf-8"?>
<configuration>   
  <appSettings>   
    <add key="DocumentsToBeFiledImageHeight" value="240"/>
    <add key="DocumentsToBeFiledImageDecodePixelHeight" value="240"/>
  </appSettings> 
</configuration>

Then in my ViewModel I’ve added these properties 

    private int _documentsToBeFiledImageDecodePixelHeight;
    public int DocumentsToBeFiledImageDecodePixelHeight
    {
      get { return _documentsToBeFiledImageDecodePixelHeight; }
      set
      {
        if (value != _documentsToBeFiledImageDecodePixelHeight)
        {
          _documentsToBeFiledImageDecodePixelHeight = value;
          RaisePropertyChanged(DocumentsToBeFiledImageDecodePixelHeightPropertyName);
        }
      }
    }

    private double _documentsToBeFiledImageHeight;
    public double DocumentsToBeFiledImageHeight
    {
      get { return _documentsToBeFiledImageHeight; }
      set
      {
        if (value != _documentsToBeFiledImageHeight)
        {
          _documentsToBeFiledImageHeight = value;
          RaisePropertyChanged(DocumentsToBeFiledImageHeightPropertyName);
        }
      }
    }

and this code

DocumentsToBeFiledImageHeight = Convert.ToDouble(ConfigurationManager.AppSettings["DocumentsToBeFiledImageHeight"]);

DocumentsToBeFiledImageDecodePixelHeight = Convert.ToInt32(ConfigurationManager.AppSettings["DocumentsToBeFiledImageDecodePixelHeight"]);

Then in the XAML I’ve added this code

<Image Grid.Row="0" Height="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.DocumentsToBeFiledImageHeight, UpdateSourceTrigger=PropertyChanged}"> 
  <Image.Source>
    <BitmapImage DecodePixelHeight="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.DocumentsToBeFiledImageDecodePixelHeight, UpdateSourceTrigger=PropertyChanged}" 
      UriSource="{Binding Path=FullName}" />
  </Image.Source>
</Image>

Unfortunately it doesn’t work, it seems that the DecodePixelHeight property is not set correctly.
Therefore, I’ve tried to recover the value directly from app.config. I’ve added these parameters in the user setting section in my app.config file

<userSettings>
    <Agest.AO.Client.Properties.Settings>
      <setting name="DocumentsToBeFiledImageDecodePixelHeight" serializeAs="String">
        <value>240</value>
      </setting>
<setting name="DocumentsToBeFiledImageHeight" serializeAs="String">
        <value>240</value>
      </setting>
    </Agest.AO.Client.Properties.Settings>
</userSettings> 

and I’ve changed the XAML code in this way

xmlns:localme="clr-namespace:Agest.AO.Client.Properties" 

<Image Grid.Row="0" Height="{Binding Source={x:Static localme:Settings.Default}, Path=DocumentsToBeFiledImageHeight, Mode=OneWay}">
  <Image.Source>
    <BitmapImage DecodePixelHeight="{Binding Source={x:Static localme:Settings.Default}, Path=DocumentsToBeFiledImageDecodePixelHeight, Mode=OneWay}"
            UriSource="{Binding Path=FullName}" />
  </Image.Source>
</Image>


Now it works and I’m able to set values directly in the configuration file.

Regards!

giovedì 28 novembre 2013

WPF (MVVM) - Retrieve the Listbox SelectedItems property

C# .NET Framework 4.0 MVVM Light Toolkit

In my WPF (MVVM) application, I want to use the Listbox SelectedItems property but this property has no setter and for this reason it’s not “bindable“ to my view model.
I have tried to use the property (IsSelected) in my object and in the XAML this item container style.

<ListBox.ItemContainerStyle>
        <Style TargetType="{x:Type ListBoxItem}">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
        </Style>
</ListBox.ItemContainerStyle>

This solution works fine if the Listbox SelectionMode property is set to Single but if the selection mode is “Extended” (SelectionMode="Extended") it doesn’t work correctly, sometimes a few items remain selected.
Finally, I found a solution that works for me. I use the MenuItem’s CommandParameter for accessing to the Listbox SelectedItems property.

Like this.

<ListBox.ContextMenu>
<ContextMenu>
                    <MenuItem Command="{Binding AddImagesSelectedCommand}" CommandParameter="{Binding PlacementTarget.SelectedItems, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}" Header="{Binding Source={StaticResource CustomResources}, Path=LocalizedStrings.mnuAddImagesSelected}" />
</ContextMenu>
</ListBox.ContextMenu> 

Then in the view model:

AddImagesSelectedCommand = new RelayCommand<object>(OnAddImagesSelected, CanAddImagesSelected);

private void OnAddImagesSelected(object param)
        {
            var selectedImages = ((IEnumerable)param).Cast<CaptureImage>().ToList();

     //To do something …           
        }   

private bool CanAddImagesSelected(object param)
        {
            if (param != null)
            {
                var selectedImages = ((IEnumerable) param).Cast<CaptureImage>().ToList();

                return (selectedImages != null && selectedImages.Count > 0);
            }
            return false;
        }

We must use the PlacementTarget object because the ContextMenu is not in the same part of the Visual Tree, so that is why you cannot use ElementName etc. to reference the ListBox.


See you soon for the next trick!