开发者

Why isn't this binding working in MVVM?

I'm setting up a binding to a ViewModel object from a WPF View, but the binding doesn't seem to be firing. I haven't done much work in MVVM, so I thought I'd ask to see if there's a reason why the binding to the image's source property isn't firing when the page is loaded.

Here's the page's XAML:

<Page x:Class="DallasPrintManager.PrintPage"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
  xmlns:viewmodel="clr-namespace:DallasPrintManager.ViewModel"
  mc:Ignorable="d" 
  d:DesignHeight="300" d:DesignWidth="900"
  DataContext="{Binding Main, Source={StaticResource PrintPage}}">
<Grid >
    <Grid.ColumnDefinitions>
        <ColumnDefinition  />
        <ColumnDefinition Width="200" />
    </Grid.ColumnDefinitions>
    <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
        <Image Source="{Binding ImageDisplay}" />
    </ScrollViewer>
</Grid>
</Page>

And here's the ViewModel:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Windows.Media.Imaging;
using System.Drawing;
using System.Windows.Input;
using DallasPrintManager.Commands;
using System.Net;
using System.IO;
using System.Windows;

public class PrintPageViewModel : INotifyPropertyChanged
{
    private BitmapImage _imageDisplay;

    public PrintPageViewModel()
    {
        ImageDisplay = getImage();
    }

    private BitmapImage getImage()
    {
        try
        {
            WebClient wc = new WebClient();
            byte[] imageData = wc.DownloadData("http://localhost/TestImage.tif");
            MemoryStream ms = new MemoryStream();
            ms.Write(imageData, 0, imageData.Length);
            System.Windows.Media.Imaging.BitmapImage wpfImg = new System.Windows.Media.Imaging.BitmapImage();
            wpfImg.BeginInit();
            wpfImg.StreamSource = ms;
            wpfImg.EndInit();
            return wpfImg;
            //return (Bitmap)Bitmap.FromStream(ms);
        }
        catch (WebException e)
        {
            MessageBox.Show("Error fetching document:\n\n" + e.Message);
            return null;
        }
        catch (Exception e)
        {
            if (e.Source == "System.Drawing")
                MessageBox.Show("Error reading document.");
            Console.Out.Write(e);
            return null;
        }
    }

    public BitmapImage ImageDisplay
    {
        get
        {
            return _imageDisplay;
        }
        set
        {
            if (value != _imageDisplay)
            {
                _imageDisplay = value;
                OnPropertyChanged("ImageDisplay");
            }
        }

    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this,
                new PropertyChangedEventArgs(propertyName));
        }
    }

}

The viewmodel is instant开发者_如何学JAVAiated in app.xaml, and bound to by the print page.


Look in your Debug Output window. Do you see any binding errors? They pretty much tell you what you need.


If the Debug Output Window is not shown you can enable it with CTRL + Alt + O.

For further information add xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase" inside your XAML and diag:PresentationTraceSources.TraceLevel=High to your binding:

<Page x:Class="DallasPrintManager.PrintPage"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
  xmlns:viewmodel="clr-namespace:DallasPrintManager.ViewModel"
  xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
  [...]
  DataContext="{Binding Main, Source={StaticResource PrintPage}}">

and:

<Image Source="{Binding ImageDisplay, diag:PresentationTraceSources.TraceLevel=High}" />

You should also make sure your properties of the bindings implement INotifyPropertyChanged if the bindings make use of UpdateSourceTrigger=PropertyChanged. Otherwise they will not update.

You can even create a dummyConverter:

public class DebugDummyConverter : IValueConverter
    {
            public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                    Debugger.Break();
                    return value;
            }

            public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                    Debugger.Break();
                    return value;
            }
    }

and add it inside your binding Converter={StaticResource DebugDummyConverter} to get information about your value of the binding, but this only works if the binding is correctly set otherwise you will not get any information.

See http://www.wpf-tutorial.com/data-binding/debugging/ for more details.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜