C# 使用WPF如何在某些情况下使用绑定对图像进行灰度化

C# 使用WPF如何在某些情况下使用绑定对图像进行灰度化,c#,wpf,data-binding,binding,converter,C#,Wpf,Data Binding,Binding,Converter,该应用程序是一个messenger,我正在其中使用microsoft lync client进行此操作。在其中一个上下文中,我在listview中获取联系人(LyncClient的对象,具有名称、图像、可用性等属性),并将其加载到数据模板中,该数据模板定义如下: <DataTemplate x:Key="ContactsTemplate"> <Grid HorizontalAlignment="Left" Width="150" Height="150" Mar

该应用程序是一个messenger,我正在其中使用microsoft lync client进行此操作。在其中一个上下文中,我在listview中获取联系人(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>

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

我建议阅读这篇关于WPF中图像处理的文章:

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

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.Source
是一个
DepencyProperty
。当类实现INotifyPropertyChanged时,您可以告诉WPF它的一个属性已更改。您只需使用更改的属性名称引发
NotifyPropertyChanged
事件。这会通知WPF更新绑定到给定属性的所有
DepencyProperty
s

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

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

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

在我的示例中,我决定存储图片。这可能不是您的最佳解决方案。它消耗更多内存,但节省处理时间。如果希望在每次可用性状态更改时重新处理映像,则应将
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();
            }
        }
    }

您可能想看看WPF着色器效果库,其中包含一个单色效果,您可以使用一些触发器@HighCore well thanx应用该效果,但问题的目的不是应用颜色效果或图像处理…我的问题更多地与绑定相关,我有一个绑定问题。请再次检查我的问题,你会发现我在问什么,但我有一个问题。在图像处理方面,这与绑定有什么不同。我的意思是,每次可用性发生变化时,也应该以这种方式执行图像处理代码。我说的对不对@bouvierr?或者,您是否尝试为同一联系人的每个可用状态设置多个图像?如果没有,那么您的交换机是如何工作的?嗯,我对C#和WPF完全陌生,所以可能我错了,这就是为什么我无法理解InotifyProperty是如何更改的,而这段代码将如何工作的?thanx mate我想对你的解决方案投赞成票,但由于我的帐户是新的,我需要15个信誉点,所以我会按照我的想法去做;)。第一个解决方案很有趣,因为它节省了处理时间,据我所知,我们必须编写逻辑,根据每个用户的可用性创建不同的图像,应用程序加载了所有联系人,对吗?如果是,那么当用户更改其帐户图片时,它将如何为不同的可用性创建图像。我认为应该如何将其与图像的NotifyPropertyChange链接,对吗?在您的第二个解决方案中,仅用于测试,我为脱机模式编写了一些代码,以使图像变为灰色,但面临一个问题,因为图像类型为Stream,转换后,我有一个FormatConvertedBitmap,我不知道如何。。。。。将其转换回流。我将添加代码作为下一条注释*******************请参阅下一条注释*******************我想如果我将其保存在一个文件中,我们可以将数据作为流读取。我搜索了如何将FormatConvertedBitmap保存到文件,但没有找到任何函数。如果您有任何解决方案,您可以建议:)
    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();
            }
        }
    }