2010-04-24 96 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