【问题标题】:Using WPF how to use Binding to Grayscale an Image on some condition使用 WPF 如何在某些条件下使用绑定对图像进行灰度化
【发布时间】:2013-01-03 17:33:27
【问题描述】:

该应用程序是一个信使,我为此目的使用 microsoft lync 客户端。在其中一种情况下,我在列表视图中获取联系人(这是 LyncClient 的一个对象,具有名称、图像、可用性等属性)并将它们加载到定义如下的数据模板中:

<DataTemplate x:Key="ContactsTemplate">
        <Grid HorizontalAlignment="Left" Width="150" Height="150" Margin="10">
            <Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}">
                <Image Source="{Binding Image}" Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}"/>
            </Border>
            <StackPanel VerticalAlignment="Bottom" Background="{Binding Availability, Converter={StaticResource AvailabilityToPresenceColor}}" Opacity="0.75">
                <TextBlock Text="{Binding Name}" Foreground="{StaticResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource TitleTextStyle}" Height="20" Margin="15,0,15,15"/>
            </StackPanel>
        </Grid>
    </DataTemplate>

它有 Grid 容器,其中我们有一个图像和文本块控件,它们显示联系人的图像和名称,如下所示,stackpanel 的背景绑定到 lync Contact 对象的可用性属性使用将可用性状态映射到颜色的转换器,例如,当联系人可用性繁忙时,stackpanel 的背景将变为红色。

我也想对图像控件有类似的效果。

我是绑定新手,所以完全迷失在这个绑定概念中。

我的想法是:图像有一个效果事件处理程序,所以我想为此目的使用它并使用

并且在某些情况下在转换器内部我想使用一些我需要获取图像源的代码,但是当我们通过绑定获取图像源时

请提出你的想法。


你可以在代码中看到 &lt;Image Source="{Binding Image}" Stretch="UniformToFill" AutomationProperties.Name="{Binding Title} effect="{Binding Availability, Converter={StaticResource AvailabilityToPresenceColor}}"/&gt; 我只是将图像控件的源绑定到 Contact 对象 的属性。我想将 Contact 对象的可用性属性发送到 IValueConverter 的 Convert 方法,或者如果可能的话,我想将图像与整个 Contact 对象绑定......或者如果有其他方式,请让我知道。

####################评论附件
var bitmap = new BitmapImage();
    bitmap.BeginInit();
    MemoreyStream ms=new MemoryStream(_image);
    bitmap.StreamSource = stream;
    bitmap.CacheOption = BitmapCacheOption.OnLoad;
    bitmap.EndInit();
 var grayBitmapSource = new FormatConvertedBitmap();
    grayBitmapSource.BeginInit();
    grayBitmapSource.Source = ms;
    grayBitmapSource.DestinationFormat = PixelFormats.Gray32Float;
    grayBitmapSource.EndInit();
.....

现在问题是我有 grayBitmapSource,它是 FormatConvertedBitmap 类型的,我不知道如何再次将其转换为 Stream。

【问题讨论】:

  • 您可能想看看 WPF 着色器效果库,其中包含可以使用一些触发器应用的单色效果 wpffx.codeplex.com
  • @HighCore 非常感谢您的回复,但问题的意图不是要应用颜色效果或图像处理......我的问题更多与绑定有关,我对绑定有疑问。请再次检查我的问题,您将能够找出我在问什么

标签: c# wpf data-binding binding converter


【解决方案1】:

我建议看一下这篇关于 WPF 中图像处理的文章:http://www.codeproject.com/Articles/237226/Image-Processing-is-done-using-WPF

使用图像处理逻辑,您可以为每个可用性状态创建不同的图片。您可以使用 IValueConverter,但这意味着您必须在每次可用性状态更改时重新处理图像。相反,您可以简单地更改您的联系人类,以便在您更改可用性属性时,它会自动向 WPF 发出信号以获取由 Image 属性引用的图片:

public class Contact : INotifyPropertyChanged
{
    // EDIT: INotifyPropertyChanged implementation.
    public event PropertyChangedEventHandler PropertyChanged;

    public void NotifyPropertyChanged(String propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    // EDIT: INotifyPropertyChanged implementation.

    private ContactAvailability _Availability;

    public ContactAvailability Availability
    {
        get { return _Availability; }
        set
        {
            _Availability = value;
            NotifyPropertyChanged("Availability");
            NotifyPropertyChanged("Image");
        }
    }

    public BitmapImage _AvailablePicture;
    public BitmapImage _BusyPicture;

    public BitmapImage Image
    {
        get
        {
            switch (this.Availability)
            {
                case ContactAvailability.Available:
                    return this._AvailablePicture;
                case ContactAvailability.Busy:
                    return this._BusyPicture;
                default:
                    throw new NotImplementedException();
            }
        }
    }
}

编辑(评论太长):

我添加了代码来实现INotifyPropertyChanged 接口。这在 WPF 中很常见,所以我认为您已经熟悉这种方法了。

在您的示例中,Image.SourceDepencyProperty。当一个类实现INotifyPropertyChanged 时,您可以告诉 WPF 它的某个属性已更改。您只需使用更改的属性名称引发NotifyPropertyChanged 事件。这会通知 WPF 更新所有绑定到给定属性的 DepencyPropertys。

这与图像处理方面的绑定有何不同。我的意思是每次可用性发生变化时,图像处理代码也应该以这种方式执行。我是对还是错@bouvierr?

没有。在这种情况下,我们将只执行固定次数的图像处理来为每个可用性状态创建图片(在我的示例中,每个联系人两次)。例如,我们可以在应用程序启动期间创建所有图片(3 个联系人 x 2 状态 = 6 个图片)并将它们存储在每个联系人的_AvailablePicture_BusyPicture 字段中。

这里是重要的部分:当我们设置Availability 属性时,我们也调用NotifyPropertyChanged("Image")。这将强制 WPF 更新 Image.Source DepencyProperty,因为它绑定到 Contact.Image。这将返回不同的图片,因为 Availability 已更改。

在我的示例中,我决定存储图片。这可能不是您的最佳解决方案。它消耗更多内存,但节省了处理时间。如果您希望在每次可用性状态更改时重新处理图像,您应该将Contact.Image 属性更改为:

    public BitmapImage Image
    {
        get
        {
            switch (this.Availability)
            {
                case ContactAvailability.Available:
                    return this._AvailablePicture;
                case ContactAvailability.Busy:
                    return GetImageWithColorFilter(this._AvailablePicture, Colors.Red);
                default:
                    throw new NotImplementedException();
            }
        }
    }

【讨论】:

  • 感谢您的回答,但我有一个问题。就图像处理而言,这与绑定有何不同。我的意思是每次可用性发生变化时,图像处理代码也应该以这种方式执行。我是对还是错@bouvierr?或者您是否尝试为同一个人联系人的每个可用性状态提供多个图像?如果没有,那么你的开关是如何工作的?好吧,我对 C# 和 WPF 完全陌生,所以我可能错了,我无法弄清楚 INotifyPropertyChanged 和这段代码将如何工作?如果你能详细说明这个逻辑是如何工作的,我会很高兴的。
  • thanx 伙计,我想为您的解决方案投票,但由于我的帐户是新帐户,因此我需要 15 点声望点,所以当我得到这些点时,我会这样做;)。 好吧第一个解决方案很有趣,因为它节省了处理时间,根据我的理解,我们必须编写逻辑来根据每个用户的可用性创建不同的图像,其中应用程序加载了所有联系人,我是正确的布维尔?如果是,那么当用户更改其帐户图片时,它将如何为不同的可用性创建图像。我认为应该如何将它与图像的 NotifyPropertyChange 联系起来,对吧?
  • 在您的第二个解决方案中,我只是为了测试而编写了一些离线模式的代码,以使图像变灰,但由于图像的类型是 Stream 并且在转换后我有一个 FormatConvertedBitmap ,所以我面临一个问题不知道如何.....将其转换回 Stream。我将添加代码作为下一条评论。 *******************参考下一条评论************************ 我想如果我把它保存在一个文件我们可以将数据作为流读取。我搜索了如何将 FormatConvertedBitmap 保存到文件中,但没有找到任何函数。如果您有任何解决方案,您可以建议:)
猜你喜欢
  • 1970-01-01
  • 2013-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-04
  • 1970-01-01
  • 2018-04-24
  • 2019-04-21
相关资源
最近更新 更多