2016-11-12 98 views
0

我正在使用XamlCropControl并试图在我的viewmodel中绑定其ImageSource属性。将XAMLCropControl ImageSource绑定到ViewModel中的ImageSource属性失败

private ImageSource source; 
    public ImageSource Source 
    { 
     get { return source; } 
     set { SetProperty(ref source, value); } 
    } 

的图像从用户的画廊挑取作为StorageFile

private async void setImageSource() 
    { 
     if (ImageStorageFile != null) 
     { 
      var imageProperties = await ImageStorageFile.Properties.GetImagePropertiesAsync(); 
      WriteableBitmap wb = new WriteableBitmap((int)imageProperties.Width, (int)imageProperties.Height); 
      IRandomAccessStream fileStream = await ImageStorageFile.OpenAsync(FileAccessMode.Read); 
      wb.SetSource(fileStream); 
      Source = wb; 
      Show(); 
     } 
    } 

在我的XAML,我有以下

<xamlcrop:CropControl Grid.Row="1" x:Name="cropControl" ImageSource="{Binding Source}" DesiredAspectRatio="{Binding AspectRatio, Mode=TwoWay}" /> 

但图像没有显示。但如果我使用样本中的路径,如

<xamlcrop:CropControl x:Name="Crop" ImageSource="ms-appx:///Assets/wrench.jpg" /> 

它的工作原理。我在CropControl.cs中设置了一个断点,实际上Writeablebitmap已传递给dependencyproperty,但未显示。我错过了什么?

回答

0

假设你已经做了所有正确的事情有关数据绑定的,然后根据你提供的,从你的代码的XamlCropControl开源,你已经设立了一个WriteableBitmapCropControlSource

您可以参考CropControl的源代码,在其Setup()DoFullLayout()方法,这些方法用于渲染此控件的图像源代码是这样的:

public void Setup() 
{ 
    // Check for loaded and template succesfully applied 
    if (!_isLoaded || 
     !_isTemplateApplied) 
    { 
     return; 
    } 

    _image.Source = ImageSource; 
    var bi = _image.Source as BitmapImage; 
    if (bi != null) 
    { 
     ... 
    } 
} 

private void DoFullLayout() 
{ 
    if (!_isTemplateApplied) 
    { 
     return; 
    } 

    var bi = _image.Source as BitmapImage; 
    if (bi == null) 
    { 
     return; 
    } 
    ... 
} 

正如你所看到的在这里,它会使用as将图像的源代码转换为BitmapImage,因为您的源代码是WriteableBitmap,因此它将无法投射并返回空值。这是您的问题的第一个可能的原因。如果您坚持使用WriteableBitmap,则需要修改这些代码以将BitmapImage更改为您的WriteableBitmap

另一个可能的问题是它的Setup方法:

var bi = _image.Source as WriteableBitmap; 
if (bi != null) 
{ 
    bi.ImageOpened += (sender, e) => 
    { 
     DoFullLayout(); 
     if (this.ImageOpened != null) 
     { 
      this.ImageOpened(this, e); 
     } 
    }; 
} 

如果传递BitmapImage为源,当我使用UriSource产生这种BitmapImage,然后一切顺利。但是当我使用SetSource来设置文件流到这个BitmapImage,然后ImageOpened事件将神奇地不是被我解雇,我不知道这里发生了什么。但是您使用的是WriteableBitmap,没有ImageOpend事件WriteableBitmap,您仍然需要修改此代码。例如,我现在正在改变它:

现在,它的工作原理,你可以自己处理异常。

因为你没有提到你使用UWP应用程序开发的模板,我在这里只是用标准的方法来实现的情况下,一个演示中,你有什么毛病数据绑定:

XAML的MainPage:

<Page.DataContext> 
    <local:MainPageViewModel x:Name="ViewModel" /> 
</Page.DataContext> 

... 
<Border Grid.Row="0" BorderBrush="Red" BorderThickness="1"> 
    <xamlcrop:CropControl x:Name="Crop" ImageSource="{Binding Source}" DesiredAspectRatio="1.0" /> 
</Border> 
<Button Content="Pick Image" Command="{Binding SetImageSource}" Grid.Row="1" /> 

MainPageViewModel:

public class MainPageViewModel : INotifyPropertyChanged 
{ 
    public MainPageViewModel() 
    { 
     source = null; 
    } 

    public ICommand SetImageSource 
    { 
     get 
     { 
      return new CommandHandler(() => this.setImageSource()); 
     } 
    } 

    public async void setImageSource() 
    { 
     StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/wrench.jpg")); 
     if (file != null) 
     { 
      using (var stream = await file.OpenReadAsync()) 
      { 
       WriteableBitmap wb = new WriteableBitmap(960, 1200); 
       wb.SetSource(stream); 
       Source = wb; 
      } 
     } 
     else 
     { 
     } 
    } 

    private ImageSource source; 

    public ImageSource Source 
    { 
     get { return source; } 
     set 
     { 
      if (value != source) 
      { 
       source = value; 
       OnPropertyChanged(); 
      } 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    private void OnPropertyChanged([CallerMemberName]string propertyName = "") 
    { 
     if (this.PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 

CommandHandler很简单这样的:

public class CommandHandler : ICommand 
{ 
    public event EventHandler CanExecuteChanged; 

    private Action _action; 

    public CommandHandler(Action action) 
    { 
     this._action = action; 
    } 

    public bool CanExecute(object parameter) 
    { 
     return true; 
    } 

    public void Execute(object parameter) 
    { 
     this._action(); 
    } 
} 
+0

非常好。我正在使用Template10,但我可以根据您的建议进行相应的调整。 – PutraKg

相关问题