Scott Olson
Scott Olson

Reputation: 4179

How to design a WPF dependency property to support the path to image?

To describe my problem i have created a small application. At first the Usercontrol:

<UserControl x:Class="WpfApplication10.UserControl1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Name="This" DataContext="{Binding ElementName=This}"
    >    
    <Image Source="{Binding Path=MyImageSource}" ></Image>
</UserControl>

second the TestApp:

<Window x:Class="WpfApplication10.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:WpfApplication10="clr-namespace:WpfApplication10"
    Title="Window1" Height="300" Width="300">
    <WpfApplication10:UserControl1
        MyImageSource="c:\test.png" >        
    </WpfApplication10:UserControl1>
</Window>

third the code behind the usercontrol

using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
namespace WpfApplication10
{
    public partial class UserControl1 : UserControl
    {
        public static readonly DependencyProperty MyImageSourceProperty =
            DependencyProperty.Register("MyImageSource", 
                 typeof(BitmapImage),typeof(UserControl1),
                 new FrameworkPropertyMetadata((BitmapImage)new BitmapImage(),
                      FrameworkPropertyMetadataOptions.None
                 ));

        public BitmapImage MyImageSource
        {
            get { return (BitmapImage)GetValue(MyImageSourceProperty); }
            set { SetValue(MyImageSourceProperty, value); }
        }


        public UserControl1()
        {
            InitializeComponent();
        }
    }
}

I know that the Type BitMapImage (of the DP) doesnt work in this way, but i want to know how to implement this feature in a clean, typesave way. I want to reach the same behaviour like the original Image.Source implementation.

thanks in advance, Scott

Upvotes: 4

Views: 7292

Answers (3)

Reda M. Hussien
Reda M. Hussien

Reputation: 1

make MyImageSource property of type string not BitmapImage

public static readonly DependencyProperty MyImageSourceProperty =
        DependencyProperty.Register("MyImageSource", 
             typeof(string),typeof(UserControl1),
new FrameworkPropertyMetadata(OnImageSourcePathChanged));

    public string MyImageSource
    {
        get { return (BitmapImage)GetValue(MyImageSourceProperty); }
        set { SetValue(MyImageSourceProperty, value); }
    }

 private static void OnImageSourcePathChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ((UserControl1)d).MyImageSource.Source = new BitmapImage(new Uri(e.NewValue as string));

    }

usage:

<WpfApplication10:UserControl1 MyImageSource="c:\test.png" > </WpfApplication10:UserControl1>

Upvotes: 0

Yogesh
Yogesh

Reputation: 14608

In your control, name your Image as:

<Image x:Name="someImage" Source="{Binding Path=MyImageSource}" ></Image>

Implement your dependency property as Uri:

public static readonly DependencyProperty MyImageSourceProperty =
    DependencyProperty.Register("MyImageSource", 
        typeof(Uri),typeof(UserControl1),
        new FrameworkPropertyMetadata(new PropertyChangedCallback(OnImageSourceChanged)));

And in OnImageSourceChanged:

private static void OnImageSourceChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
    UserControl1 userControl = (UserControl1)sender;

    userControl.someImage.Source = new BitmapImage((Uri) e.NewValue);
}

This way, you can supply a string path to the dependency property which will be converted to Uri automatically.

EDIT: In Image, the source property is implemented as ImageSource instead of Uri (an abstract class, from which your implementation, i.e. BitmapSource, also derives). It also implements a OnSourceChanged event just like I have implemented one for Uri. The conclusion is, that you will have to use a change event if you want to set the source of an image.

Upvotes: 5

Ilya Khaprov
Ilya Khaprov

Reputation: 2524

You need to create a converter. since your DP defined to be Bitmapimage and in XAML you bind it to string.

Maybe you can find suitable converter here. http://www.codeplex.com/wpfconverters

or try to google "WPF converters"

public object Convert(object value, Type targetType,
                      object parameter, CultureInfo culture)
{
    try
    {
        return new BitmapImage(new Uri((string)value));
    }
    catch 
    {
        return new BitmapImage();
    }
}

public object ConvertBack(object value, Type targetType,
                          object parameter, CultureInfo culture)
{
    throw new NotImplementedException();
}

}

and let your MyImageSource be typeof string. Then you can use converter inside UserControl definition.

Upvotes: 1

Related Questions