2010-04-24 102 views
0

我正在開始使用WPF,並試圖讓我的頭將數據連接到UI。我設法連接到一個類沒有任何問題,但我真正想要做的是連接到主窗口的屬性。WPF數據模板

這裏的XAML:

<Window x:Class="test3.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:custom="clr-namespace:test3" 
    Title="MainWindow" Height="350" Width="525"> 
<Window.Resources> 
    <CollectionViewSource 
     Source="{Binding Source={x:Static Application.Current}, Path=Platforms}" 
     x:Key="platforms"/> 
    <DataTemplate DataType="{x:Type custom:Platform}"> 
     <StackPanel> 
      <CheckBox IsChecked="{Binding Path=Selected}"/> 
      <TextBlock Text="{Binding Path=Name}"/> 
     </StackPanel> 
    </DataTemplate> 
</Window.Resources> 
<Grid> 
    <ListBox ItemsSource="{Binding Source={StaticResource platforms}}"/> 
</Grid> 

這裏的主窗口中的代碼:

public partial class MainWindow : Window 
{ 
    ObservableCollection<Platform> m_platforms; 

    public MainWindow() 
    { 
     m_platforms = new ObservableCollection<Platform>(); 

     m_platforms.Add(new Platform("PC")); 

     InitializeComponent(); 
    } 

    public ObservableCollection<Platform> Platforms 
    { 
     get { return m_platforms; } 
     set { m_platforms = value; } 
    } 
} 

這裏的平臺類:

public class Platform 
{ 
    private string m_name; 
    private bool m_selected; 

    public Platform(string name) 
    { 
     m_name = name; 
     m_selected = false; 
    } 

    public string Name 
    { 
     get { return m_name; } 
     set { m_name = value; } 
    } 

    public bool Selected 
    { 
     get { return m_selected; } 
     set { m_selected = value; } 
    } 
} 

這所有的編譯和運行良好,但列表框中沒有任何內容。如果我在平臺的get方法上放置一個斷點,它不會被調用。我不明白,因爲平臺是XAML應該連接到的!

回答

2

除了BindingSourceCollectionViewSource的不正確之外,您的代碼看起來沒問題。你大概意思是:

<CollectionViewSource 
    Source="{Binding Source={x:Static Application.Current}, Path=MainWindow.Platforms}" 
    x:Key="platforms"/> 

沒有這種更改綁定居然找了物業PlatformsApplication實例。

+0

是的,這讓它工作。我也改變了StackPanel方向,否則複選框出現在名稱上方。 – imekon 2010-04-24 09:17:05

1

我建議你將平臺不添加到MainWindow,而是將其設置爲MainWindow的DataContext(包裝在ViewModel中)。

這樣你可以非常容易地綁定它(綁定代碼看起來像ItemsSource = {綁定路徑=平臺})。

這是WPF設計的一部分,每個表單都應該有一個明確的DataContext綁定。

+0

我將不得不調查DataContext以瞭解它們如何工作,謝謝 – imekon 2010-04-24 09:16:25

1

一個更合適的解決方案是給你的窗口一個名字。一個很好的約定是_this。

<Window x:Name="_this" x:Class="test3.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:custom="clr-namespace:test3" 
    Title="MainWindow" Height="350" Width="525"> 
    <Window.Resources> 
     <CollectionViewSource 
      Source="{Binding ElementName=_this, Path=Platforms}" 
      x:Key="platforms"/> 
     <DataTemplate DataType="{x:Type custom:Platform}"> 
      <StackPanel> 
       <CheckBox IsChecked="{Binding Path=Selected}"/> 
       <TextBlock Text="{Binding Path=Name}"/> 
      </StackPanel> 
     </DataTemplate> 
    </Window.Resources> 
    <Grid> 
     <ListBox ItemsSource="{Binding Source={StaticResource platforms}}"/> 
    </Grid> 
+0

這更優雅! – imekon 2010-04-25 06:51:24

0

這是我更新的代碼中,XAML:

<Window x:Name="_this" 
    x:Class="test3.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:custom="clr-namespace:test3" 
    Title="MainWindow" Height="190" Width="177"> 
    <Window.Resources> 
     <CollectionViewSource 
      Source="{Binding ElementName=_this, Path=Platforms}" 
      x:Key="platforms"/> 
     <DataTemplate x:Key="platformTemplate" DataType="{x:Type custom:Platform}"> 
      <StackPanel Orientation="Horizontal"> 
       <CheckBox Margin="1" IsChecked="{Binding Path=Selected}"/> 
       <TextBlock Margin="1" Text="{Binding Path=Name}"/> 
      </StackPanel> 
     </DataTemplate> 
    </Window.Resources> 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition /> 
      <RowDefinition Height="23" /> 
      <RowDefinition Height="23" /> 
     </Grid.RowDefinitions> 
     <ListBox Grid.Row="0" 
      ItemsSource="{Binding Source={StaticResource platforms}}" 
      ItemTemplate="{StaticResource platformTemplate}"/> 
     <Button Click="OnBuild" Grid.Row="1">Build...</Button> 
     <Button Click="OnTogglePC" Grid.Row="2">Toggle PC</Button> 
    </Grid> 
</Window> 

的XAML代碼背後:

public partial class MainWindow : Window 
{ 
    ObservableCollection<Platform> m_platforms; 

    public MainWindow() 
    { 
     m_platforms = new ObservableCollection<Platform>(); 

     m_platforms.Add(new Platform("PC")); 
     m_platforms.Add(new Platform("PS3")); 
     m_platforms.Add(new Platform("Xbox 360")); 

     InitializeComponent(); 
    } 

    public ObservableCollection<Platform> Platforms 
    { 
     get { return m_platforms; } 
     set { m_platforms = value; } 
    } 

    private void OnBuild(object sender, RoutedEventArgs e) 
    { 
     string text = ""; 

     foreach (Platform platform in m_platforms) 
     { 
      if (platform.Selected) 
      { 
       text += platform.Name + " "; 
      } 
     } 

     if (text == "") 
     { 
      text = "none"; 
     } 

     MessageBox.Show(text, "WPF TEST"); 
    } 

    private void OnTogglePC(object sender, RoutedEventArgs e) 
    { 
     m_platforms[0].Selected = !m_platforms[0].Selected; 
    } 
} 

...最後是平臺的代碼,增強玩完兩雙向交互:

public class Platform : INotifyPropertyChanged 
{ 
    private string m_name; 
    private bool m_selected; 

    public Platform(string name) 
    { 
     m_name = name; 
     m_selected = false; 
    } 

    public string Name 
    { 
     get { return m_name; } 
     set 
     { 
      m_name = value; 

      OnPropertyChanged("Name"); 
     } 
    } 

    public bool Selected 
    { 
     get { return m_selected; } 
     set 
     { 
      m_selected = value; 

      OnPropertyChanged("Selected"); 
     } 
    } 

    private void OnPropertyChanged(string name) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(name)); 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
} 
0

使用DataC ontext,它變得更加容易!

<Window x:Class="test5.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:custom="clr-namespace:test5" 
    Title="MainWindow" Height="190" Width="177"> 
    <Window.Resources> 
     <CollectionViewSource 
      Source="{Binding Path=.}" 
      x:Key="platforms"/> 
     <DataTemplate x:Key="platformTemplate" DataType="{x:Type custom:Platform}"> 
      <StackPanel Orientation="Horizontal"> 
       <CheckBox Margin="1" IsChecked="{Binding Path=Selected}"/> 
       <TextBlock Margin="1" Text="{Binding Path=Name}"/> 
      </StackPanel> 
     </DataTemplate> 
    </Window.Resources> 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition /> 
      <RowDefinition Height="23" /> 
      <RowDefinition Height="23" /> 
     </Grid.RowDefinitions> 
     <ListBox Grid.Row="0" 
      ItemsSource="{Binding Source={StaticResource platforms}}" 
      ItemTemplate="{StaticResource platformTemplate}"/> 
     <Button Click="OnBuild" Grid.Row="1">Build...</Button> 
     <Button Click="OnTogglePC" Grid.Row="2">Toggle PC</Button> 
    </Grid> 
</Window> 

下面是這背後的代碼:

private ObservableCollection<Platform> m_platforms; 

public MainWindow() 
{ 
    InitializeComponent(); 

    m_platforms = new ObservableCollection<Platform>(); 

    m_platforms.Add(new Platform("PC")); 
    m_platforms.Add(new Platform("PS3")); 
    m_platforms.Add(new Platform("Xbox 360")); 

    DataContext = m_platforms; 
} 

public void OnBuild(object sender, RoutedEventArgs e) 
{ 
    string text = ""; 

    foreach (Platform platform in m_platforms) 
    { 
     if (platform.Selected) 
     { 
      text += platform.Name + " "; 
     } 
    } 

    if (text == "") 
    { 
     text = "none"; 
    } 

    MessageBox.Show(text, "WPF TEST"); 
} 

public void OnTogglePC(object sender, RoutedEventArgs e) 
{ 
    m_platforms[0].Selected = !m_platforms[0].Selected; 
} 

請注意,我已經放棄了需要申報的平臺作爲主窗口的屬性,而不是我把它分配到DataContext和XAML源變成,簡單地說,「。」

+0

這很奇怪,這個答案出現在以下之前,但我稍後添加它... – imekon 2010-04-25 07:51:49

+0

他們按排名排序 – nedruod 2010-04-25 16:31:32

+0

順便說一下,很確定你不需要Path =。,簡單地{Binding}是等價的。 – nedruod 2010-04-25 16:33:04