In our daily development, Image controls are often used. By setting the Source property of the Image control, we can load images. When setting the source property of the Image, we can use relative paths or absolute paths. Generally speaking, we recommend using absolute paths, similar to the following form Source="/Demo;Component/Images/", where Demo represents the name of the project, and then indicates which image resource is below which folder. In the program, we can even set the X:Name property for the Image control and dynamically change the Source of Image in the background code. However, I personally think this method is not suitable for the maximum number of image switching, and it increases the coupling between the View layer and the code. It is not the core design idea of compound MVVM, so today I will summarize the dynamic binding form of Image.
To bind, it must be bound to the Source property of the Image control. First, we need to figure out what the type of Source is, public ImageSource Source { get; set; } is the ImageSource type. Of course, when we bind, the bitmap image BitmapImage is the most used. Let's first look at the inheritance relationship of BitmapImage: BitmapImage: BitmapSource: ImageSource, which is ultimately an ImageSource type. Of course, in our Model layer, we can also directly define a BitmapImage property, and then bind this property directly to the Image Source. Of course, in this article, we define a String type of ImgSource, so we must define a converter Converter, and the corresponding codes are posted here.
First of all, the View layer is relatively simple:
<Grid ="1"> <Image Source="{Binding Path=,Converter={StaticResource MyImageConverter}}" Stretch="Fill"> </Image> </Grid>
Then let's take a look at the Model layer is also very simple.
public class LTEModel : BaseModel { private string _imageSource = null; public string ImgSource { get { return _imageSource; } set { if (value != _imageSource) { _imageSource = value; FirePropertyChanged("ImgSource"); } } } }
Then there is the important converter:
public class StringToImageSourceConverter:IValueConverter { #region Converter public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { string path = (string)value; if (!(path)) { return new BitmapImage(new Uri(path, )); } else { return null; } } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return null; } #endregion }
Then there is the important converter:
public class StringToImageSourceConverter:IValueConverter { #region Converter public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { string path = (string)value; if (!(path)) { return new BitmapImage(new Uri(path, )); } else { return null; } } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return null; } #endregion }
The converter returns an Object type, and the actual return is a BitmapImage object. Therefore, when writing program binding, we must clarify the relationship between the bound target and the object. This is very important.
The following is to add bindings in the ViewModel layer and update the data source. Here is a timer to update the data source regularly:
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 distribution by region", Time = () }; } return _baseModel; } set { if (value != _baseModel) { _baseModel = value; FirePropertyChanged("BaseModelInstance"); } } } private List<string> imgList = new List<string>(); private void GetImageSource() { //Read the path of the corresponding resource through the assembly string assemblyLocation = ().; string assLocation = (0, ("\\")); string[] img_files = (("{0}\\Images", assLocation), "*.JPG"); foreach (string img_path in img_files) { (img_path); } } private void InitTimer() { myDispatcher = new DispatcherTimer(); += new EventHandler(Timer_Tick); = (1000); (); } private void Timer_Tick(object sender, EventArgs e) { int imageIndex = 0; if ( > 0 && LTEModel != null) { imageIndex = (0, ); = imgList[imageIndex]; } if (_baseModel != null) { _baseModel.Time = (); } } }
Then instantiate a ViewModel object and bind it to the front desk. This idea is actually quite clear.
In fact, in many cases, we do not know what pictures we need to bind, or bind pictures according to the data type. This is often used when defining data templates. Let me introduce the following to bind the corresponding pictures according to the type. Then by definition
public enum DeviceType { SheXiangJi, KaKou, DianZiJingCha, MingJin }
This type is bound to different pictures through different types. This is also a very important application. We must pay attention to the method we use. Here is a brief introduction.
<ItemsControl ItemsSource="{Binding DeviceList,RelativeSource={RelativeSource TemplatedParent}}" ="2"> <> <ControlTemplate TargetType="ItemsControl"> <UniformGrid Columns="3" Rows="7" IsItemsHost="True"></UniformGrid> </ControlTemplate> </> <> <DataTemplate> <StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Margin="20 0 0 0" VerticalAlignment="Center" SnapsToDevicePixels="True"> <Image x:Name="icon1" Width="48" Height="48" ="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> <> <DataTrigger Binding="{Binding Type}" Value="SheXiangJi"> <Setter Property="Source" Value="/;component/images/" TargetName="icon1"></Setter> </DataTrigger> <DataTrigger Binding="{Binding Type}" Value="KaKou"> <Setter Property="Source" Value="/;component/images/" TargetName="icon1"></Setter> </DataTrigger> <DataTrigger Binding="{Binding Type}" Value="DianZiJingCha"> <Setter Property="Source" Value="/;component/images/" TargetName="icon1"></Setter> </DataTrigger> <DataTrigger Binding="{Binding Type}" Value="MingJin"> <Setter Property="Source" Value="/;component/images/Police_A.png" TargetName="icon1"></Setter> </DataTrigger> </> </DataTemplate> </> </ItemsControl>
In addition, what is very similar to Image is <ImageBrush ImageSource="/;component/images/" Stretch="Fill"></ImageBrush>
The usage is similar, and you can also add images through binding. However, when using it, you still need to pay attention to setting the current image generation operation to Resource.
The above is the detailed content of the binding method of the C# WPF Image control. For more information about the C# WPF Image control, please follow my other related articles!