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
}
轉換器返回的是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" Sn apsToDevicePixels="True">
<Image x:Name="icon1" Width="48" Height="48" RenderOptions.BitmapScalingMode="NearestNeighbor" VerticalAli gnment="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>
用法也差不多,同樣可以通過綁定的方式來添加圖片,不過在使用的時候還是需要注意一下的。

