2010-08-19 3 views
0

Я пытаюсь связать класс данных с элементом управления ListView в WPF, но не могу заставить его работать. Я могу связать его во время выполнения и заставить его работать, используя следующее:Привязка элемента управления к классу данных с использованием WPF/XAML

this.DataContext = DataSet; 

Но, если бы я попробовать следующее в WPF/XAML это не работает, которая выглядит следующим образом:

DataContext="DiscoveredItemContainer" 

Я пробовал различные перестановки, но ничего не пытаюсь работать. Я мог бы просто использовать версию во время выполнения, поскольку это работает, но это подтачивает меня, что я не могу заставить XAML связать элемент управления правильно. Возможно, это не сработает, поскольку набор данных носит динамический характер, но это всего лишь мысль.

Я не уверен, что код поможет ответить на вопрос или нет, но я опубликую то, что уместно, я надеюсь, что как-то. Я отказался от использования объявлений.

Это 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 

Наконец, это класс, который выставит переменную, которая 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

Установив свой DataContext в XAML, вы решили создать экземпляр нового 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> 

Вы должны также Gut все ссылки на 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

Блестящий, отлично работает. Мне просто нужно было изменить эти несколько строк, как вы заявляли, компилировали и запускали проект, а затем bam! Отлично работает! Наконец, это либо метод предпочтительнее, чем другой? – lordhog

+0

Это действительно вопрос предпочтения. Но в целом, чем чище будет разделение между пользовательским интерфейсом и «деловой» логикой, тем лучше будет. В этом смысле ваш вид (код XAML) не должен знать и не заботится о том, каков его контекст данных, до тех пор, пока DiscoveredItems существует где-то там. Поэтому я предлагаю вам отменить все, что я только что написал, установить DiscoveredItemContainer как общедоступное свойство, а затем установить this.DataContext = DiscoveredItemContainer. В конечном итоге это будет меньше хлопот. – bufferz

+0

Вы также получите средний уровень между вашим пользовательским интерфейсом и классом DiscoveredItemsContainer. Это будет ViewModel. Если вы еще не изучили мир MVVM, пожалуйста, возьмите некоторых из них, чтобы посмотреть это отличное видео: http://blog.lab49.com/archives/2650 Ваш WPF и навыки привязки будут сниматься как ракета один раз вы получите MVVM, и вы будете писать более чистый код, чем когда-либо. – bufferz

1

вы должны заменить

DataContext="DiscoveredItemContainer" 

по

DataContext="{Binding DiscoveredItemContainer}" 
+0

Это не будет работать, потому что (а) DiscoveredItemContainer является частным, (b), DataContext не является текущим объектом –

Смежные вопросы