2011年3月30日 星期三

WPF資料繫結-DataContext

 

若有一WPF視窗包含以下XAML,Grid包含三個控制項TextBox、Label與TextBlock
<Grid x:Name="grid1">
<TextBox Height="23" HorizontalAlignment="Left" Margin="34,26,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" />
<Label Content="Label" Height="28" HorizontalAlignment="Left" Margin="34,68,0,0" Name="label2" VerticalAlignment="Top" Width="132" />
<TextBlock Height="23" HorizontalAlignment="Left" Margin="34,0,0,127" Name="textBlock1" Text="TextBlock" VerticalAlignment="Bottom" Width="125" />
</Grid>
如果為這三個控制項的屬性設定資料繫時都指定了相同的Source,那麼就代表Source要設三次,後續要更改Source時,就得改三遍。如果多個資料繫結共用了相同的Source,您可以使用DataContext來簡化設計。在WPF中每一個繼承自FrameworkElement的類別都有DataContext屬性。
利用Expression Blend 4,選取畫面上的Grid,從屬性視窗點選DataContext後方的「New」按鈕。
clip_image002
選取要繫結的自訂物件,以MyDataClass2為例:
clip_image004
Code:
public class MyDataClass2 : INotifyPropertyChanged {
       public event PropertyChangedEventHandler PropertyChanged;   
       private string _MyProperty="";
       public string MyProperty {
           get { return _MyProperty; }
           set {
               if ( _MyProperty != value ) {
                   _MyProperty = value;
                   PropertyChanged ( this , new PropertyChangedEventArgs ( "MyProperty" ) );                  
               }
           }
       }
   }
回到設計畫面,點選Label控制項Context屬性後方的Advanced Properties->Data Binding->選取要繫結到MyDataClass2的MyProperty。
clip_image006
按照相同的步驟為TextBlock和TextBox控制項的Text屬性進行相同的資料繫結設定。
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:wpfDataBinding" x:Class="wpfDataBinding._7_DataContext"
Title="_7_DataContext" Height="300" Width="300">
<Grid x:Name="grid1">
<Grid.DataContext>
<local:MyDataClass2/>
</Grid.DataContext>
<TextBox Height="23" HorizontalAlignment="Left" Margin="34,26,0,0" x:Name="textBox1" VerticalAlignment="Top" Width="120" />
<Label Content="{Binding MyProperty}" Height="28" HorizontalAlignment="Left" Margin="34,68,0,0" x:Name="label2" VerticalAlignment="Top" Width="132" />
<TextBlock Height="23" HorizontalAlignment="Left" Margin="34,0,0,127" x:Name="textBlock1" Text="{Binding MyProperty}" VerticalAlignment="Bottom" Width="125" />
</Grid>
</Window>

2011年3月9日 星期三

WPF UI Localization

1.新建立一個Wpfapplication
2.加入Resource File
image
3.設name/value pair,並將Access Modifier設為public
image
4.複製Resource1.resx,再貼上修改新檔名為Resource1.zh-TW.resx
image
5.修改value
image
6.在XAML引用namespace,並使用static關鍵字進行繫結
image
7.設UICluture
image
8.Run

2011年3月4日 星期五

WPF4-使用CollectionViewSource排序、篩選資料

我們可以使用這段XAML呼叫System.IO下Directory類別的EnumerateFiles方法將C:\下所有檔案列在ListBox

<Window x:Class="CollectionViewSourceDemo.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="300" Width="300"
        xmlns:io="clr-namespace:System.IO;assembly=mscorlib"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        >
    <Window.Resources>
        <ObjectDataProvider x:Key="myProvider"
                            ObjectType="{x:Type io:Directory}" MethodName="EnumerateFiles">
            <ObjectDataProvider.MethodParameters>
                <sys:String>C:\</sys:String>              
            </ObjectDataProvider.MethodParameters>
        </ObjectDataProvider>
    </Window.Resources>
    <Grid>
        <ListBox ItemsSource="{Binding Source={StaticResource myProvider}}"/>
    </Grid>
</Window>

執行結果參考如下

image

改用CollectionViewSource 設排序方向性為Descending

<Window x:Class="CollectionViewSourceDemo.Window3"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="300" Width="300"
        xmlns:io="clr-namespace:System.IO;assembly=mscorlib"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
    xmlns:d="clr-namespace:System.Windows.Data;assembly=PresentationFramework"
        xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
        >
    <Window.Resources>
        <ObjectDataProvider x:Key="myProvider"
                            ObjectType="{x:Type io:Directory}" MethodName="EnumerateFiles">
            <ObjectDataProvider.MethodParameters>
                <sys:String>C:\</sys:String>
            </ObjectDataProvider.MethodParameters>
        </ObjectDataProvider>
        <CollectionViewSource x:Key="myViewSource" Source="{StaticResource myProvider}">
            <CollectionViewSource.SortDescriptions>
                <scm:SortDescription    Direction="Descending" />
            </CollectionViewSource.SortDescriptions>

        </CollectionViewSource>
    </Window.Resources>
    <Grid>
        <ListBox ItemsSource="{Binding Source={StaticResource myViewSource}}"/>
    </Grid>
</Window>

加上Filter事件

<Window x:Class="CollectionViewSourceDemo.Window4"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="300" Width="300"
        xmlns:io="clr-namespace:System.IO;assembly=mscorlib"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        xmlns:d="clr-namespace:System.Windows.Data;assembly=PresentationFramework"
        xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
        >
    <Window.Resources>
        <ObjectDataProvider x:Key="myProvider"
                            ObjectType="{x:Type io:Directory}" MethodName="EnumerateFiles">
            <ObjectDataProvider.MethodParameters>
                <sys:String>C:\</sys:String>
            </ObjectDataProvider.MethodParameters>
        </ObjectDataProvider>
        <CollectionViewSource            
            x:Key="myViewSource" Source="{StaticResource myProvider}"
            Filter="CollectionViewSource_Filter"
            >
            <CollectionViewSource.SortDescriptions>
                <scm:SortDescription    Direction="Descending" />
            </CollectionViewSource.SortDescriptions>
        </CollectionViewSource>
    </Window.Resources>
    <Grid>
        <ListBox ItemsSource="{Binding Source={StaticResource myViewSource}}"/>
    </Grid>
</Window>

然後在cs檔案中,加入

private void CollectionViewSource_Filter(object sender, FilterEventArgs e) {
           string f = e.Item.ToString();
           if (f.EndsWith(".txt"))
               e.Accepted = true;
           else
               e.Accepted = false;
       }

就可以篩選副檔名為.txt檔案出來

image

ObjectDataProvider與資料繫結

WPF若要將物件當作資料進行繫結,可以利用ObjectDataProvider來提供資料,例如以下範例,利用myObject自訂物件GetCollection' 法取回的List<String>集合當作資料來源以進行繫結
class myObject {
        public List<string> GetCollection() {       
            return  new List<string> { "AA", "BB", "CC" };
        }
    }
接著就可以在WPF視窗中加一個ObjectDataProvider ,設定要呼叫myObject的GetCollection  Method,取回的集合可以直接繫結到ListBox
<Window x:Class="Demo.ODP01"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ODP01" Height="300" Width="300"       
        xmlns:local="clr-namespace:Demo">
    <Window.Resources>
        <ObjectDataProvider x:Key="myObjectProvider"
                            ObjectType="{x:Type  local:myObject}"
                            MethodName="GetCollection" />
    </Window.Resources>
    <Grid>
        <ListBox
            ItemsSource="{Binding Source={StaticResource myObjectProvider}}"
            Height="158" HorizontalAlignment="Left" Margin="36,12,0,0" Name="listBox1" VerticalAlignment="Top" Width="198" />
    </Grid>
</Window>
執行結果
image

2011年2月21日 星期一

使用PresentationTraceSources.TraceLevel除錯

WPF在進行DataBinding的過程中,若發生錯誤,並不會以未處理的Exception型式告知,因此你將無法寫程式利用傳統的try..catch區塊來捕捉錯誤,你可以利用 PresentationTraceSources.TraceLevel來得知更多錯誤資訊幫助除錯,例如有一個WPF程式包含以下類別



public class MyUser {
       public string UserName { get; set; }       
   }

文字方塊繫結如下
<TextBox>
           <TextBox.Text>
               <Binding Path="Name" />
           </TextBox.Text>
       </TextBox>

MainWindow Contructor如下
public MainWindow() {
          InitializeComponent();
          this.DataContext = new MyUser() {  UserName = "Mary" };
      }

執行後檢視Output Window只看到Error 40的訊息
image
重寫一下設定,Textbox設定TraceLevel為High

<Window x:Class="P5_21_TraceLevel.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
       
         xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
        >
    <Grid x:Name="roor">    
        <TextBox>
            <TextBox.Text>
                <Binding Path="Name"
               diag:PresentationTraceSources.TraceLevel="High"/>
            </TextBox.Text>
        </TextBox>
    </Grid>
</Window>

適當設定Visual Studio 2010 Debugging
image

重Run,Output window會多顯示更多的資訊出來
image

總網頁瀏覽量