C# WPF Image控件的绑定方法

在我们平时的开发中会经常用到Image控件,通过设置Image控件的Source属性,我们可以加载图片,设置Image的source属性时可以使用相对路径也可以使用绝对路径,一般情况下建议使用绝对路径,类似于下面的形式Source="/Demo;Component/Images/Test.jpg"其中Demo表示工程的名称,后面表示具体哪个文件夹下面的哪个图片资源,在程序中,我们甚至可以为Image控件设置X:Name属性,在后台代码中动态去改变Image的Source,但我个人认为这种方式不太适合最大量的图片切换,而且增加了View层和代码之间的耦合性,不是和复合MVVM的核心设计思想,所以今天就总结一下Image的动态绑定的形式。

要绑定,肯定是绑定到Image控件的Source属性上面,我们首先要搞清楚Source的类型是什么,public ImageSource Source { get; set; }也就是ImageSource类型,当然在我们绑定的时候用的最多的就是BitmapImage这个位图图像啦,我们首先来看看BitmapImage的继承关系:BitmapImage:BitmapSource:ImageSource,最终也是一种ImageSource类型。当然在我们的Model层中我们也可以直接定义一个BitmapImage的属性,然后将这个属性直接绑定到Image的Source上面,当然这篇文章我们定义了一个ImgSource的String类型,所以必须要定义一个转换器Converter,这里分别贴出相应地代码。

首先是View层,比较简单:

    <Grid Grid.Row="1">
      <Image Source="{Binding Path=LTEModel.ImgSource,Converter={StaticResource MyImageConverter}}" Stretch="Fill">
      </Image>
    </Grid>

然后我们再来看看Model层也很简单。

public class LTEModel : BaseModel
  {
    private string _imageSource = null;
    public string ImgSource
    {
      get
      {
        return _imageSource;
      }
      set
      {
        if (value != _imageSource)
        {
          _imageSource = value;
          FirePropertyChanged("ImgSource");
        }
      }
    }
  }

然后就是重要的转换器:

public class StringToImageSourceConverter:IValueConverter
  {
    #region Converter

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
      string path = (string)value;
      if (!string.IsNullOrEmpty(path))
      {
        return new BitmapImage(new Uri(path, UriKind.Absolute));
      }
      else
      {
        return null;
      }
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
      return null;
    }
    #endregion
  }

然后就是重要的转换器:

public class StringToImageSourceConverter:IValueConverter
  {
    #region Converter

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
      string path = (string)value;
      if (!string.IsNullOrEmpty(path))
      {
        return new BitmapImage(new Uri(path, UriKind.Absolute));
      }
      else
      {
        return null;
      }
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
      return null;
    }
    #endregion
  }

转换器返回的是Object类型,实际返回的是一个BitmapImage对象。所以我们在写程序绑定的时候一定要弄清绑定的目标和对象之间的关系,这个是非常重要的。

下面就是在ViewModel层中来添加绑定,并更新数据源,这里使用的是一个定时器来定时更新数据源:

public class LTEViewModel : NotifyObject
  {
    private DispatcherTimer myDispatcher = null;
    private Random random = new Random();
    public LTEViewModel()
    {
      GetImageSource();
      InitTimer();
    }

    private LTEModel _lteModel = null;
    public LTEModel LTEModel
    {
      get
      {
        if (_lteModel == null)
        {
          _lteModel = new LTEModel();
        }
        return _lteModel;
      }
      set
      {
        if (value != _lteModel)
        {
          _lteModel = value;
          FirePropertyChanged("LTEModel");
        }
      }
    }

    private BaseModel _baseModel = null;
    public BaseModel BaseModelInstance
    {
      get
      {
        if (_baseModel == null)
        {
          _baseModel = new BaseModel()
          {
            Title = "分地区LTE分布",
            Time = DateTime.Now.ToString()
          };
        }
        return _baseModel;
      }
      set
      {
        if (value != _baseModel)
        {
          _baseModel = value;
          FirePropertyChanged("BaseModelInstance");
        }
      }
    }

    private List<string> imgList = new List<string>();
    private void GetImageSource()
    {
      //通过程序集来读取相应的资源的路径
      string assemblyLocation = this.GetType().Assembly.Location;
      string assLocation = assemblyLocation.Substring(0, assemblyLocation.LastIndexOf("\\"));
      string[] img_files = Directory.GetFiles(string.Format("{0}\\Images", assLocation), "*.JPG");
      foreach (string img_path in img_files)
      {
        imgList.Add(img_path);
      }
    }

    private void InitTimer()
    {
      myDispatcher = new DispatcherTimer();
      myDispatcher.Tick += new EventHandler(Timer_Tick);
      myDispatcher.Interval = TimeSpan.FromMilliseconds(1000);
      myDispatcher.Start();
    }

    private void Timer_Tick(object sender, EventArgs e)
    {
      int imageIndex = 0;
      if (imgList.Count > 0 && LTEModel != null)
      {
        imageIndex = random.Next(0, imgList.Count);
        LTEModel.ImgSource = imgList[imageIndex];
      }
      if (_baseModel != null)
      {
        _baseModel.Time = DateTime.Now.ToString();
      }
    }
  }

然后就是实例化一个ViewModel对象绑定到前台中,这个思路其实是相当明确的。

其实在我们的很多时候,我们并不知道我们需要绑定什么图片,或者说根据数据类型来绑定图片,这个在定义数据模板的时候经常使用到,下面就介绍一下,根据类型来绑定相应的图片。然后通过定义

public enum DeviceType
{  
  SheXiangJi,
  KaKou,
  DianZiJingCha,
  MingJin
}

这种类型,通过不同的类型来绑定到不同的图片,这个也是一个非常重要的应用,我们一定要注意使用的方法,这里只是简单介绍一下。

<ItemsControl ItemsSource="{Binding DeviceList,RelativeSource={RelativeSource TemplatedParent}}" Grid.Row="2">
              <ItemsControl.Template>
                <ControlTemplate TargetType="ItemsControl">
                  <UniformGrid Columns="3" Rows="7" IsItemsHost="True"></UniformGrid>
                </ControlTemplate>
              </ItemsControl.Template>
              <ItemsControl.ItemTemplate>
                <DataTemplate>
                  <StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Margin="20 0 0 0" VerticalAlignment="Center" SnapsToDevicePixels="True">
                    <Image x:Name="icon1" Width="48" Height="48" RenderOptions.BitmapScalingMode="NearestNeighbor" VerticalAlignment="Center"></Image>
                    <TextBlock Margin="10 0 0 0" Foreground="#fff" ToolTip="{Binding Name}" FontSize="40" Text="{Binding Name}" HorizontalAlignment="Left" VerticalAlignment="Center"></TextBlock>
                  </StackPanel>
                  <DataTemplate.Triggers>
                    <DataTrigger Binding="{Binding Type}" Value="SheXiangJi">
                      <Setter Property="Source" Value="/IGisControls.JTJ.UIControls;component/images/camera.png" TargetName="icon1"></Setter>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding Type}" Value="KaKou">
                      <Setter Property="Source" Value="/IGisControls.JTJ.UIControls;component/images/Bayonet.png" TargetName="icon1"></Setter>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding Type}" Value="DianZiJingCha">
                      <Setter Property="Source" Value="/IGisControls.JTJ.UIControls;component/images/epolice.png" TargetName="icon1"></Setter>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding Type}" Value="MingJin">
                      <Setter Property="Source" Value="/IGisControls.JTJ.UIControls;component/images/Police_A.png" TargetName="icon1"></Setter>
                    </DataTrigger>
                  </DataTemplate.Triggers>
                </DataTemplate>
              </ItemsControl.ItemTemplate>
            </ItemsControl>

另外和Image很类似的就是 <ImageBrush ImageSource="/IGisControls.JTJ.UIControls;component/images/screenBG.jpg" Stretch="Fill"></ImageBrush>

用法也差不多,同样可以通过绑定的方式来添加图片,不过在使用的时候还是需要注意一下就是设置当前图片的生成操作为Resource。

以上就是C# WPF Image控件的绑定方法的详细内容,更多关于C# WPF Image控件的资料请关注我们其它相关文章!

(0)

相关推荐

  • c# WPF设置软件界面背景为MediaElement并播放视频

    在我们的常见的软件界面设计中我们经常会设置软件的背景为SolidColorBrush或者LinerColorBrush.RadialGradientBrush 等一系列的颜色画刷为背景,有时我们也会使用ImageBrush添加图片来作为界面的背景,另外常用的还有DrawingBrush以及今天需要进行总结的VisualBrush,这些我们都是比较容易实现的,那么我们如果想将软件的界面设计成一个动画或者干脆播放一段视频作为背景,这个对于整个软件的效果又是一个巨大的提升. 首先我们来看看backgr

  • c# WPF中如何自定义MarkupExtension

    在介绍这一篇文章之前,我们首先来回顾一下WPF中的一些基础的概念,首先当然是XAML了,XAML全称是Extensible Application Markup Language (可扩展应用程序标记语言),是专门用于WPF技术中的UI设计语言,通过使用XAML语言,我们能够快速设计软件界面,同时能够通过绑定这种机制能够很好地实现界面和实现逻辑之间的解耦,这个就是MVVM模式的核心了,那么今天我们介绍的MarkupExtension和XAML之间又有哪些的关系呢? Markup Extensio

  • C# wpf Brush转Hex字符串的实例代码

    我就废话不多说了,大家还是直接看代码吧~ //from MaterialDesignDemo.Converters public class BrushToHexConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value == null) return null; string lowerH

  • c# WPF中System.Windows.Interactivity的使用

    背景 在我们进行WPF开发应用程序的时候不可避免的要使用到事件,很多时候没有严格按照MVVM模式进行开发的时候习惯直接在xaml中定义事件,然后再在对应的.cs文件中直接写事件的处理过程,这种处理方式写起来非常简单而且不用过多地处理考虑代码之间是否符合规范,但是我们在写代码的时候如果完全按照WPF规范的MVVM模式进行开发的时候就应该将相应的事件处理写在ViewModel层,这样整个代码才更加符合规范而且层次也更加清楚,更加符合MVVM规范. 常规用法 1 引入命名空间 通过在代码中引入Syst

  • 在C# WPF下自定义滚动条ScrollViewer样式的操作

    一.实现对ScrollViewer样式的自定义主要包括: 1.滚动条宽度设置 2.滚动条颜色 3.滚动条圆角 4.滚动条拉动时的效果mouseover 二.实现效果: 三.实现方法 1.创建资源字典( ResourceDictionary)文件 由于style代码比较多,之间在控件文件中加载style比较混乱,也不利于其它窗口复用,这里单独创建了ScrollViewDictionary.xaml文件代码如下: <ResourceDictionary xmlns="http://schema

  • C# WPF 父控件通过使用可视化树找到子控件的示例代码

    在我们使用WPF设计前台界面时,经常会重写数据模板,或者把控件放到数据模板里.但是一旦将控件放到数据模板中,在后台就没有办法通过控件的名字来获取它了,更没办法对它进行操作(例如,隐藏,改变控件的某个值). 如果你是比我还白的小白,对我刚刚陈述的东西不清楚,接下来我简单说一下什么是把控件放在数据模板中,怎么样的情况没法后台通过名字来获取控件,如果读者对于数据模板这些事儿已经清楚了,或者只关心如何使用可视化树可以将这部分跳过哈. 先上代码介绍一下什么是数据模板以WPF中ListBox控件为例: <L

  • C# WPF上位机实现和下位机TCP通讯的方法

    下位机使用北京大华程控电源DH1766-1,上位机使用WPF.实现了电压电流实时采集,曲线显示.上午在公司调试成功,手头没有程控电源,使用TCP服务端模拟.昨天写的TCP服务端正好排上用场. 界面如下: 服务端 服务端实在上篇基础上实现的.需要做如下更改: while (true) { try { byte[] bufferDate = new byte[1024]; int realLen = pSocket.Receive(bufferDate); if (realLen <= 0) { t

  • C# WPF 建立无边框(标题栏)的登录窗口的示例

    前言:笔者最近用c#写WPF做了一个项目,此前未曾做过完整的WPF项目,算是一边学一边用,网上搜了不少资料,效率当然是不敢恭维的,有时会在一些很简单的问题上纠结很长时间,血与泪的教训可不少. 不过,正如电视剧某榜里的一句话:既然我活了下来,就不会白白活着!笔者怎么也算挣扎过了,有些经验与教训可以分享,趁着记忆深刻总结写下来.希望后来者少走弯路,提高工作效率.如果有写得不好的地方,希望读者能够指正,一起进步! --------------------------------- 今天先从登录窗口说起

  • C# WPF使用AForge类库操作USB摄像头拍照并保存

    项目中用到 USB 摄像头,需要根据情况进行图像抓拍,查了半天资料,比较多的是使用 WPFMediaKit 和 AForge . 但是由于项目要求不显示 USB 摄像头拍摄的画面,最终确定使用 AForge 解决. 下面用一个测试程序记录一下. 一.无预览拍照 首先建立一个 WPF 项目,我的就叫 AForgeTest,你们随意就好: 然后在 NuGet 包管理器中安装 AForge 库: 我只安装了图中打勾的几个库,这个根据自己项目需要安装就好. 不过用 USB 摄像头拍照必须安装: AFor

  • c# WPF如何实现滚动显示的TextBlock

    在我们使用TextBlock进行数据显示时,经常会遇到这样一种情况就是TextBlock的文字内容太多,如果全部显示的话会占据大量的界面,这是我们就会只让其显示一部分,另外的一部分就让其随着时间的推移去滚动进行显示,但是WPF默认提供的TextBlock是不具备这种功能的,那么怎么去实现呢? 其实个人认为思路还是比较清楚的,就是自己定义一个UserControl,然后将WPF简单的元素进行组合,最终实现一个自定义控件,所以我们顺着这个思路就很容易去实现了,我们知道Canvas这个控件可以通过设置

  • c# WPF实现Windows资源管理器(附源码)

      今天我来写一篇关于利用WPF来实现Windows的资源管理器功能,当然只是局部实现这个功能,因为在很多时候我们需要来实现对本机资源的管理,当然我们可以使用OpenFileDialog dialog = new OpenFileDialog()这个Microsoft.Win32命名空间下的这个类来实现一些资源查找和导入的功能,但是在很多时候我们可能需要更多的功能,并且希望能够集成到我们自己的项目中,但是我们这个时候就不得不自己来写一套来集成到我们的软件中去了,因为OpenFileDialog这

  • C#中WPF依赖属性的正确学习方法

    前言 我在学习WPF的早期,对依赖属性理解一直都非常的不到位,其恶果就是,我每次在写依赖属性的时候,需要翻过去的代码来复制黏贴. 相信很多朋友有着和我相同的经历,所以这篇文章希望能帮助到那些刚刚开始学依赖属性的朋友. 那些[讨厌]的依赖属性的讲解文章 初学者肯定会面临一件事,就是百度,谷歌,或者MSDN来查看依赖属性的定义和使用,而这些文章虽然都写的很好,但,那是相对于已经学会使用依赖属性的朋友而言. 而对于初学者而言,说是误导都不过分. 比如,官网的这篇文章https://docs.micro

  • C# 使用WPF 用MediaElement控件实现视频循环播放

    在WPF里用MediaElement控件,实现一个循环播放单一视频的程序,同时可以控制视频的播放.暂停.停止. 一种方式,使用MediaElement.MediaEnded事件,在视频播放结束后,自动重新播放: 另一种方式,使用WPF定时器,在定时器事件里写入视频播放代码. 后者优点是可以控制循环时长,不必等到视频播放结束就可以开始下一次播放,比如:同时启动多个播放程序,使多个时长不同的视频同时播放,无限循环,如果采用第一种方式,累计多次自动播放后,视频内容就无法同步. 第一种方式: XAML:

随机推荐