惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园_首页
雷峰网
雷峰网
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
WordPress大学
WordPress大学
腾讯CDC
T
Tailwind CSS Blog
A
About on SuperTechFans
H
Hackread – Cybersecurity News, Data Breaches, AI and More
The GitHub Blog
The GitHub Blog
T
The Blog of Author Tim Ferriss
G
Google Developers Blog
The Cloudflare Blog
D
DataBreaches.Net
Recent Announcements
Recent Announcements
Engineering at Meta
Engineering at Meta
B
Blog
博客园 - 聂微东
阮一峰的网络日志
阮一峰的网络日志
月光博客
月光博客
博客园 - 司徒正美
MongoDB | Blog
MongoDB | Blog
Google DeepMind News
Google DeepMind News
Apple Machine Learning Research
Apple Machine Learning Research

博客园 - Sheva

Two Xaml Tricks - Sheva I See Cool Stuff Today DataTemplate Is A Bit Naughtier To Play With XmlnsDefinitionAttribute Is Pretty Nifty Application.DoEvents In WPF 征召译者 C# Trivia Test CreateParams Is Pretty Cool! In-Place Editing In WPF SingleLinkedList Implementation C# Application Markup Language Regex 101 Exercise I10 - Extract repeating hex blocks from a string AvalonPaint: Features Added Regex 101 Exercise I9 - Count the number of matches Crossbow: Hosting WPF Controls In Winforms Application Crossbow? WTF? The Architecture Of Avalon Drop Shadow Effect In WPF XamlReader.Load(): Build Up Your Own XamlPad
Data Binding In WPF
Sheva · 2006-04-06 · via 博客园 - Sheva
   

Data binding is a very important feature in every development platform, for all of you who have been using the data binding mechanism of ASP.NET, you must think that data binding in ASP.NET is quite flexible, and extensible, you can declaratively bind the data to any property for any web control, when the data is changed through user interactituon with the interface, the underlying data store will be changed accordingly. fortunately WPF comes up with another quite similar data binding mechanism which can make data access super easy for developers. For demonstration purpose I plan to write a slide show application which will take advantage of data binding capability in WPF, with this application, you can select a set of images through a dialog, and the application will recursively display those images one at a time, so the slide show effects can be achieved.
    First of all, I need to write a helper class which will perform the actual slide show operations behind the scene:

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.ComponentModel;
using System.Collections.ObjectModel;namespace SlideShow
{
    
public class SlideShowManager: INotifyPropertyChanged
    {
        
public event PropertyChangedEventHandler PropertyChanged;
        
private String[] imageFiles;
        
private Int32 interval = 2;
        
private Int32 currentIndex = 0;
        
private DispatcherTimer timer;
        
private Image targetImage;public SlideShowManager(String[] imageFiles)
        {
            
this.imageFiles = imageFiles;
            timer 
= new DispatcherTimer();
            timer.Interval 
= new TimeSpan(00, interval);
            timer.Tick 
+= TimerOnTick;
            timer.Start();
        }
public Image TargetImage
        {
            
get { return targetImage; }
            
set { targetImage = value; }
        }
public BitmapImage Current
        {
            
get
            {
                currentIndex 
= (currentIndex + 1% imageFiles.Length;
                
return new BitmapImage(new Uri(imageFiles[currentIndex], UriKind.Absolute));
            }
        }
public Int32 Interval
        {
            
get { return interval; }
            
set 
            {
                
if (value > 0)
                {
                    timer.Stop();
                    timer.Interval 
= new TimeSpan(00, value);
                    timer.Start();
                }
            }
        }
private void FadeIn()
        {
            DoubleAnimation fadeInAnimation 
= new DoubleAnimation(0.11, TimeSpan.FromSeconds(Interval));
            targetImage.BeginAnimation(Image.OpacityProperty, fadeInAnimation);
        }
private void TimerOnTick(Object sender, EventArgs e)
        {
            
if (imageFiles != null && imageFiles.Length > 1)
            {
                FadeIn();
                
if (PropertyChanged != null) PropertyChanged(thisnew PropertyChangedEventArgs("Current"));
            }
        }
    }
}


    Note that this class implements the INotifyPropertyChanged event, for any object which wants to act as data source object, it should  implement this  interface,  basically  this interface  provides  a notifcation  mechanism  in the data  binding scenario,  when any property  of this  class  is  changed,  it will send  a notification to the  data binding  UI elements, so the UI elements can see the change and refresh its visual display accordingly.
    Now I have the house keeping class at hand, what I need then is a UI which hosts an Image element, whose Source property is bound to the SlideShowManager's Current property:

<Window x:Class="SlideShow.MainWindow"
    xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
    Title
="SlideShow" Height="300" Width="300"
    
>
  
<Window.CommandBindings>
    
<CommandBinding Command="ApplicationCommands.Open" Executed="OpenCommandExecutedHandler" />
    
<CommandBinding Command="ApplicationCommands.Close" Executed="CloseCommandExecutedHandler" />
  
</Window.CommandBindings>
  
<DockPanel>
    
<Menu DockPanel.Dock="Top">
      
<MenuItem Header="_File">
        
<MenuItem Header="_Open" Name="menuOpen" Command="ApplicationCommands.Open" />
        
<MenuItem Header="E_xit" Name="menuExit" Command="ApplicationCommands.Close"/>
      
</MenuItem>
    
</Menu>
      
<Image x:Name="slideshowImage" Opacity="1"/>
  
</DockPanel>
</Window>


In the code beside file for this XAML file, I write some lines of code like this:

using System;
using System.Windows.Input;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;namespace SlideShow
{
    
public partial class MainWindow : Window
    {
        
private SlideShowManager manager;
        
public MainWindow()
        {
            InitializeComponent();
        }
private void OpenSlideShow()
        {
            Microsoft.Win32.OpenFileDialog dlg 
= new Microsoft.Win32.OpenFileDialog();
            dlg.Filter 
= dlg.Filter = "PNG file(*.png)|*.png|BMP file(*.bmp)|*.bmp|JPEG file(*.jpg)|*.jpg|GIF file(*.gif)|*.gif|Image Files(*.*) | *.*";
            dlg.FilterIndex 
= 3;
            dlg.InitialDirectory 
= System.Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
            dlg.Multiselect 
= true;
            
if (dlg.ShowDialog() == true)
            {
                manager 
= new SlideShowManager(dlg.FileNames);
                manager.Interval 
= 2;
                manager.TargetImage 
= slideshowImage;
                Binding binding 
= new Binding("Current");
                
using (binding.DeferChanges())
                {
                    binding.Mode 
= BindingMode.OneWay;
                    binding.Source 
= manager;
                }

                BindingOperations.SetBinding(slideshowImage, Image.SourceProperty, binding);
            }
        }

private void OpenCommandExecutedHandler(Object sender, ExecutedRoutedEventArgs e)
        {
            OpenSlideShow();

            Binding binding = new Binding("Current");
                
using (binding.DeferChanges())
                {
                    binding.Mode 
= BindingMode.OneWay;
                    binding.Source 
= manager;
                }

                BindingOperations.SetBinding(slideshowImage, Image.SourceProperty, binding);


        }private void CloseCommandExecutedHandler(Object sender, ExecutedRoutedEventArgs e)
        {
            Application.Current.Shutdown();
        }
    }
}


    You can see from this code that in the OpenSlideShow() method, I open up a OpenFileDialog control so user can select a set of images he or she want to show up, and then I create the data binding code like following:

Binding binding = new Binding("Current");
                
using (binding.DeferChanges())
                {
                    binding.Mode 
= BindingMode.OneWay;
                    binding.Source 
= manager;
                }

                BindingOperations.SetBinding(slideshowImage, Image.SourceProperty, binding);

    This is the actual data binding operation I want to talk about, so you must be surprised by how easy data binding can be achieved in WPF. in fact, you also can declaratively perform the data binding operation in XAML, for example:

<Window x:Class="RssReader.Window1"
    xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
         xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
    Title
="RssReader" Height="444" Width="619">
  
<Window.Resources>
    
<XmlDataProvider x:Key="RssData" Source="http://sheva.cnblogs.com/Rss.aspx" IsAsynchronous="True"/>
  
</Window.Resources>
  
<DockPanel>
    
<Label DockPanel.Dock="Top" FontSize="14" FontWeight="Bold"
             Content
="{Binding Source={StaticResource RssData}, XPath=/rss/channel/title}"/>
    
<Label DockPanel.Dock="Top"
              Content
="{Binding Source={StaticResource RssData}, XPath=/rss/channel/description}" />
    
<DockPanel DockPanel.Dock="Top"
                    DataContext
="{Binding Source={StaticResource RssData}, XPath=/rss/channel/item}">
      
<ScrollViewer DockPanel.Dock="Left" >
        
<ListBox ItemsSource="{Binding}"
                      Width
="200"
                      IsSynchronizedWithCurrentItem
="True">
          
<ListBox.ItemTemplate>
            
<DataTemplate>
              
<TextBlock Text="{Binding XPath=title}" />
            
</DataTemplate>
          
</ListBox.ItemTemplate>
        
</ListBox>
      
</ScrollViewer>
      
<Frame Source="{Binding XPath=link}" Width="Auto"/>
    
</DockPanel>
  
</DockPanel>
</Window>


This markup can build a very simple RSS reader application, quite stunning is isn't?