2010-08-19 87 views
0

我想將數據類綁定到WPF中的ListView控件,但似乎無法使其工作。我可以在運行時綁定,並得到它的工作使用下列內容:使用WPF/XAML將控件綁定到數據類

this.DataContext = DataSet; 

但是,如果我嘗試在WPF/XAML以下是不工作,看起來像:

DataContext="DiscoveredItemContainer" 

我嘗試了各種排列,但沒有嘗試。我可以使用運行時版本,因爲它的工作原理,但是它讓我感到困惑,因爲我無法使XAML正確地綁定控件。也許這是行不通的,因爲數據集本質上是動態的,但這只是一個想法。

我不確定代碼是否有助於回答問題,但我會發布相關的內容,希望如何。我遺漏了使用聲明。

這是形式

<Window x:Class="Viking.Test.DataBindTest" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:Items="clr-namespace:Viking.Test.Discovery" 
xmlns:data="clr-namespace:Viking.Test" 
Title="Data Binding Test" Height="300" Width="500" 
DataContext="DiscoveredItemContainer"> 
    <DockPanel Name="_DockPanel" Height="Auto" Width="Auto"> 
    <Menu Name="_Menu" DockPanel.Dock="Top" Height="22" Width="Auto" VerticalContentAlignment="Center" VerticalAlignment="Top"> 
     <MenuItem Name="_File" Header="File"> 
     <MenuItem Name="_AddOne" Header="Add One" Click="AddOne_Click" /> 
     </MenuItem> 
    </Menu> 
    <ListView Name="listView1" Height="Auto" Width="Auto" ItemsSource="{Binding Path=DiscoveredItems}"> 
     <ListView.View> 
     <GridView AllowsColumnReorder="True"> 
      <GridViewColumn Header="Field1" DisplayMemberBinding="{Binding Field1}" Width="100" /> 
     </GridView> 
     </ListView.View> 
    </ListView> 
    </DockPanel> 
</Window> 

在這裏是與XAML

namespace Viking.Test 
{ 
    public partial class DataBindTest : Window 
    { 
     private DiscoveredItemList DiscoveredItemContainer; 

     public DataBindTest() 
     { 
      InitializeComponent(); 
      DiscoveredItemContainer = new DiscoveredItemList(); 
      // Uncomment the following line to get the databinding to work 
      // this.DataContext = DiscoveredItemContainer; 
     } 

     private void AddOne_Click(object sender, RoutedEventArgs e) 
     { 
      DiscoveredItemContainer.AddRandomItem(); 
     } 
    } // End of Class 
} // End of Namespace 

The following is the class that contains the dataset 
namespace Viking.Test.Discovery 
{ 
    public class DiscoveredItem 
    { 

     public DiscoveredItem() 
     { 
     } 

     public string Field1 { get; set; } 

    } // End of Class 
} // End of Namespace 

最後變爲局部類的XAML,這是將暴露的變量,它是的ObservableCollection在類爲了將數據綁定到類

namespace Viking.Test.Discovery 
{ 
    class DiscoveredItemList 
    { 
     public ObservableCollection<DiscoveredItem> DiscoveredItems { get; set; } 
     private Random RandomGen; 

     public DiscoveredItemList() 
     { 
      DiscoveredItems = new ObservableCollection<DiscoveredItem>(); 
      RandomGen = new Random(); 
     } 

     public void AddRandomItem() 
     { 
      DiscoveredItem di = new DiscoveredItem();; 
      di.Field1 = RandomGen.Next(1,10).ToString(); 
      DiscoveredItems.Add(di); 
     } 
    } // End of Class 
} // End of Namespace 

我見過很多數字將控件綁定到表單上的另一個控件或運行時綁定的條目(這是我如何使其工作)或綁定到靜態資源的文章。
任何洞察力,爲什麼我不能得到這種方法的工作表示讚賞。
謝謝。

馬克

回答

3

通過XAML設置你的DataContext,你決定實例化,而不是綁定到一個在新DiscoveredItemList你的代碼隱藏。因此,您的代碼隱藏不會直接引用DiscoveredItemList,但您始終可以按名稱搜索它。

你需要做的第一件事就是刪除:

DataContext="DiscoveredItemContainer" 

,並替換爲:

<Window.Resources> 
    <Items:DiscoveredItemList x:Key="Context"></Items:DiscoveredItemList> 
</Window.Resources> 

此實例化一個新的對象,你現在的XAML可以綁定到。你的列表視圖應該綁定到它是這樣的:

<ListView Name="listView1" Height="Auto" Width="Auto" DataContext="{StaticResource Context}" ItemsSource="{Binding DiscoveredItems}"> 
... 
</ListView> 

你還必須在你的代碼腸道出DiscoveredItemContainer所有引用的後面,當你要訪問的項目:DiscoveredItemList,如添加一個新的隨機項目,請執行此操作:

private void AddOne_Click(object sender, RoutedEventArgs e) 
{ 
    var list = this.Resources["Context"] as DiscoveredItemList; 
    list.AddRandomItem(); 
} 

如果您願意,您也許可以存儲對該項目的本地引用。

下面是您的複製/粘貼樂趣的完整代碼。請注意,我測試過這一點, 「我的作品」:P

namespace Viking.Test 
{ 
    public partial class DataBindTest : Window 
    { 
     public DataBindTest() 
     { 
      InitializeComponent(); 
     } 

     private void AddOne_Click(object sender, RoutedEventArgs e) 
     { 
      var list = this.Resources["Context"] as DiscoveredItemList; 
      list.AddRandomItem(); 
     } 
    } // End of Class 
} // End of Namespace 

//The following is the class that contains the dataset 
namespace Viking.Test.Discovery 
{ 
    public class DiscoveredItem 
    { 
     public DiscoveredItem() { } 

     public string Field1 { get; set; } 

    } // End of Class 

    public class DiscoveredItemList 
    { 
     public ObservableCollection<DiscoveredItem> DiscoveredItems { get; set; } 
     private Random RandomGen; 

     public DiscoveredItemList() 
     { 
      DiscoveredItems = new ObservableCollection<DiscoveredItem>(); 
      RandomGen = new Random(); 
     } 


     public void AddRandomItem() 
     { 
      DiscoveredItem di = new DiscoveredItem(); ; 
      di.Field1 = RandomGen.Next(1, 10).ToString(); 
      DiscoveredItems.Add(di); 
     } 
    } // End of Class 
} 

XAML:

<Window x:Class="Viking.Test.DataBindTest" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Items="clr-namespace:Viking.Test.Discovery" xmlns:data="clr-namespace:Viking.Test" Title="Data Binding Test" Height="300" Width="500" > 
    <Window.Resources> 
     <Items:DiscoveredItemList x:Key="Context"></Items:DiscoveredItemList> 
    </Window.Resources> 
    <DockPanel Name="_DockPanel" Height="Auto" Width="Auto" > 
     <Menu Name="_Menu" DockPanel.Dock="Top" Height="22" Width="Auto" VerticalContentAlignment="Center" VerticalAlignment="Top"> 
      <MenuItem Name="_File" Header="File"> 
       <MenuItem Name="_AddOne" Header="Add One" Click="AddOne_Click" /> 
      </MenuItem> 
     </Menu> 
     <ListView Name="listView1" Height="Auto" Width="Auto" DataContext="{StaticResource Context}" ItemsSource="{Binding DiscoveredItems}"> 
      <ListView.View> 
       <GridView AllowsColumnReorder="True"> 
        <GridViewColumn Header="Field1" DisplayMemberBinding="{Binding Field1}" Width="100" /> 
       </GridView> 
      </ListView.View> 
     </ListView> 
    </DockPanel> 
</Window> 

參考: Silverlight - Setting DataContext in XAML rather than in constructor?

+0

輝煌,效果很好。我只需要按照你的陳述,編譯,然後運行這個項目就可以改變這些行,然後再運行!工作很棒!最後,哪種方法比其他方法更可取? – lordhog 2010-08-19 16:57:24

+0

這確實是一個偏好問題。但總的來說,用戶界面和「商業」邏輯之間的分離越乾淨越好,你會變得越好。從這個意義上說,只要DiscoveredItems存在於某處,View(XAML代碼)就不應該知道也不關心它的數據上下文是什麼。所以我建議你撤銷我剛剛發佈的所有內容,將DiscoveredItemContainer設置爲公共屬性,然後設置this.DataContext = DiscoveredItemContainer。從長遠來看,這將不那麼麻煩。 – bufferz 2010-08-19 17:11:58

+0

您也可以在UI和DiscoveredItemsContainer類之間建立中間層。那將是一個ViewModel。如果你還沒有探索MVVM的世界,請花點時間觀看這個優秀的視頻:http://blog.lab49.com/archives/2650 你的WPF和綁定技能將像火箭一樣起飛您將獲得MVVM的竅門,並且您將比以往更清晰地編寫代碼。 – bufferz 2010-08-19 17:13:46

1

就應該更換

DataContext="DiscoveredItemContainer" 

通過

DataContext="{Binding DiscoveredItemContainer}" 
+0

這是行不通的,因爲(a)DiscoveredItemContainer是私有的,(b),DataContext不是當前對象 – 2010-08-19 10:18:50