c# - XAML:用户控件未将更改传播到绑定(bind)源

标签 c# xaml binding user-controls windows-runtime

我正在为 Metro UI 开发 ImagePicker 用户控件。它的原理很简单:它显示一个图像,当点击该图像时,会打开一个文件对话框,允许更改当前图像。为了实现这一点,用户控件只需公开一个 ImageSource 属性即可将包装的图像绑定(bind)到该属性。

<local:ImagePicker Source="{Binding PictureUri, Mode=TwoWay}"/>

启动时,绑定(bind)工作正常,并显示我的 View 模型提供的 PictureUri 属性中的图片。问题是,当我点击图像并选择一张新图像时,会显示新图像,但尽管采用了 TwoWay 绑定(bind)模式,但绑定(bind)值不会在我的 View 模型中更新。我相信这个问题来 self 的用户控制代码,但我不明白为什么当它实际传播到包装图像时,该值没有传播到 View 模型......

这是 XAML 部分。

<UserControl x:Name="ImagePickerUserControl"
    x:Class="ImageUserControl.ImagePicker"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Grid x:Name="ImagePickerRootGrid" Background="Gray">
        <Image Source="{Binding Source, ElementName=ImagePickerUserControl}"/>
    </Grid>

</UserControl>

还有代码部分,抱歉有点长,但我相信这里的一切都很重要。

public sealed partial class ImagePicker : UserControl
{
    public ImagePicker()
    {
        this.InitializeComponent();

        // Hookup event to handle when the control is tapped
        this.Tapped += ImagePicker_Tapped;
    }

    public static readonly DependencyProperty SourceProperty =
        DependencyProperty.Register("Source", typeof(ImageSource), typeof(ImagePicker),
        new PropertyMetadata(null, new PropertyChangedCallback(ImagePicker.OnSourceChanged)));

    public ImageSource Source
    {
        get
        {
            return (ImageSource)this.GetValue(ImagePicker.SourceProperty);
        }

        set
        {
            this.SetValue(ImagePicker.SourceProperty, value);
        }
    }

    private static void OnSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        // Update Visual State
    }

    private async void ImagePicker_Tapped(object sender, TappedRoutedEventArgs e)
    {
        // Pick up a new picture
        FileOpenPicker filePicker = new FileOpenPicker();
        filePicker.FileTypeFilter.Add(".jpg");
        filePicker.FileTypeFilter.Add(".jpeg");
        filePicker.FileTypeFilter.Add(".png");
        var pngFile = await filePicker.PickSingleFileAsync();

        // If the user picked up a file
        if (pngFile != null)
        {
            BitmapImage bitmap = new BitmapImage();
            await bitmap.SetSourceAsync(await pngFile.OpenReadAsync());

            // Update the source image
            this.Source = bitmap;
        }
    }
}

我相信这个问题只是我的一个错误,但我无法理解这里发生了什么。如果您想尝试运行该项目并更好地查看代码,我已将其上传并在 SkyDrive 上共享:ImageUserControl

感谢您耐心阅读这么长的帖子。

最佳答案

两种方式绑定(bind)不起作用,因为您的依赖项属性的类型为 ImageSource,而 View 模型属性的类型为 Uri。绑定(bind)无法将 ImageSource 转换为 Uri,因此未设置该值。您的用户控件上需要一个 Uri 类型的属性才能使双​​向绑定(bind)起作用。

编辑:

如果您仅将依赖属性更改为其他类型,则当用户选择您的应用在没有选择器的情况下无法访问的文件时,内部图像将不再显示。您的应用只能使用返回的 StorageFile 来访问此类文件,而不是使用其绝对路径。在控件内部,您可以通过使用两个依赖属性来解决这个问题:ImageSource 就像现在一样用于显示内部图像,Uri 用于返回路径。由于您将绑定(bind)到第二个,因此您需要添加一个回调,当“Uri”从外部发生更改时,该回调将设置 ImageSource 属性。

根据您想要对用户控件之外的结果执行的操作,这对您来说可能仍然不够好。如果您想访问那里的文件,您需要返回一个 StorageFile 或将该文件放入 FutureAccessList 中。并返回 token 。

关于c# - XAML:用户控件未将更改传播到绑定(bind)源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14015459/

相关文章:

c# - Jwt Bearer 和依赖注入(inject)

c# - 在 Windows 8 中使用 C# 设置菜单 Flyout 背景颜色

c# - 在后面的代码中获取和设置绑定(bind)转换器

xaml - 绑定(bind) XAML 中的 XPath 语法

c# - 从数组中取出两个数,使和为常数

c# - 如何通过 renderpartial 将两个变量传递给控件?

c# - Windows Phone 键盘打开事件和属性

c# - CollectionViewSource,如何过​​滤数据?

c# - 为什么检测到正在更改的对象属性但未检测到刷新对象

c# - 强制 Nuget 包使用特定版本的子依赖项?