2015-07-29 2 views
0

Итак, я проверил множество ответов, которые я нашел по разным темам, но мое приложение WPF не обновляет связанные данные. Когда я устанавливаю все свойства перед инициализацией MainWindow Data, отображаются правильно, но перед загрузкой данных мне нужно выбрать каталог, дату и т. Д. Пытался изменить DataContext в коде, но ИТ не работает. Все классы, используемые в качестве VieModels, реализовали интерфейс INotifyPropertyChanged (но значения PropertyChanged всегда равны нулю). Я из идей теперь ...WPF Обновление DataBinding

Это XAML код:

<Window x:Class="WpfDataBinding.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:WpfDataBinding" 
     mc:Ignorable="d" 
     Title="MainWindow" Height="600" Width="800" Name="Logs"> 
    <Window.DataContext> 
     <local:CustomDataContexts /> 
    </Window.DataContext> 
    <Grid Name="Logi"> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="*"/> 
      <RowDefinition Height="Auto"/> 
      <RowDefinition Height="Auto"/> 
      <RowDefinition Height="Auto"/> 
     </Grid.RowDefinitions> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="Auto"/> 
      <ColumnDefinition Width="*"/> 
      <ColumnDefinition Width="*"/> 
      <ColumnDefinition Width="Auto"/> 
     </Grid.ColumnDefinitions> 
     <local:CustomButton Grid.Column="0" Grid.Row="1" Margin="5" Height="35" Width="100" x:Name="Choose" Text="Wybierz:" ImageSource="Resources/choose.png" Click="CustomButton_Click" /> 
     <local:CustomButton Grid.Column="0" Grid.Row="2" Margin="5" Height="35" Width="100" x:Name="Load" Text="Załaduj:" ImageSource="Resources/load.png" Click="CustomButton_Click" /> 
     <local:CustomButton Grid.Column="0" Grid.Row="3" Margin="5" Height="35" Width="100" x:Name="Search" Text="Szukaj:" ImageSource="Resources/search.png" Click="CustomButton_Click" /> 
     <local:CustomButton Grid.Column="3" Grid.Row="2" Margin="5" Height="80" Width="100" x:Name="Next" Grid.RowSpan="2" Text="Dalej:" ImageSource="Resources/next.png" Click="CustomButton_Click" /> 
     <TabControl DataContext="{Binding TextViewModel}" x:Name="tabControl" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" ItemsSource="{Binding TxtView.Tabs, ElementName=Logs, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"> 
      <TabControl.ItemTemplate> 
       <!-- this is the header template--> 
       <DataTemplate> 
        <TextBlock Text="{Binding Header}" /> 
       </DataTemplate> 
      </TabControl.ItemTemplate> 
      <TabControl.ContentTemplate > 
       <!-- this is the body of the TabItem template--> 
       <DataTemplate> 
        <ListView ItemsSource="{Binding EntryViewModels}"> 
         <ListView.ItemTemplate> 
          <DataTemplate> 
           <TextBlock Text="{Binding Entry.Tag}"/> 
          </DataTemplate> 
         </ListView.ItemTemplate> 
        </ListView> 
       </DataTemplate> 
      </TabControl.ContentTemplate> 
     </TabControl> 
     <TabControl DataContext="{Binding SingleNode}" x:Name="tabControl2" Grid.Row="0" Grid.Column="2" Grid.ColumnSpan="2" ItemsSource="{Binding Tabs}"> 
      <TabControl.ItemTemplate> 
       <!-- this is the header template--> 
       <DataTemplate> 
        <TextBlock Text="{Binding Header}" /> 
       </DataTemplate> 
      </TabControl.ItemTemplate> 
      <TabControl.ContentTemplate> 
       <DataTemplate> 
        <ListView ItemsSource="{Binding Content}" /> 
       </DataTemplate> 
      </TabControl.ContentTemplate> 
     </TabControl> 
    </Grid> 
</Window> 

Code-за выглядит следующим образом:

public CustomDataContexts DataContexts { get; set; } 
    public string Path { get; set; } 
    public Files Files { get; set; } 

    public MainWindow() 
    { 
     /*Path = @"C:\Users\Slawek\Desktop\Logs\logi"; 
     Files = new Files(Path); 
     Files.NarrowFiles(false, DateTime.MinValue); 
     var entry = new EntryCollection(Files.SelectedFiles[1], Files.SelectedFiles, null); 
     TxtView = new TxtViewModel(new List<TxtTabItem>(new[] { new TxtTabItem(entry) }));*/ 
     InitializeComponent(); 
    } 

    private void CustomButton_Click(object sender, RoutedEventArgs e) 
    { 
     var fe = (FrameworkElement) sender; 
     switch (fe.Name) 
     { 
      case "Choose": 
       var g = new FolderBrowserDialog(); 
       if (g.ShowDialog() == System.Windows.Forms.DialogResult.OK) 
        Path = g.SelectedPath; 
       break; 
      case "Load": 
       DataContexts = new CustomDataContexts(); 
       Files = new Files(Path); 
       Files.NarrowFiles(false, DateTime.MinValue); 
       var entry = new EntryCollection(Files.SelectedFiles[1], Files.SelectedFiles, null); 
       DataContexts.TextViewModel = new TxtViewModel(new List<TxtTabItem>(new[] { new TxtTabItem(entry) })); 
       break; 
      case "Search": 
       break; 
      case "Next": 
       break; 
     } 
    } 

CustomDataContexts класс:

public class CustomDataContexts : INotifyPropertyChanged 
{ 
    private TxtViewModel textViewModel; 
    public XmlViewModel SingleNode { get; set; } 

    public TxtViewModel TextViewModel 
    { 
     get { return textViewModel; } 
     set { OnPropertyChanged("TextViewModel"); } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected virtual void OnPropertyChanged(string propertyName) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

EntryViewModel:

public class EntryViewModel : INotifyPropertyChanged 
{ 
    private SingleEntry entry; 

    public SingleEntry Entry 
    { 
     get { return entry; } 
     set 
     { 
      entry = value; 
      OnPropertyChanged("Entry"); 
     } 
    } 

    public EntryViewModel(SingleEntry entry) 
    { 
     Entry = entry; 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected virtual void OnPropertyChanged(string propertyName) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

TxtViewModel:

public class TxtViewModel :INotifyPropertyChanged 
{ 
    private ObservableCollection <TxtTabItem> tabs; 

    public ObservableCollection<TxtTabItem> Tabs 
    { 
     get { return tabs; } 
     set 
     { 
      tabs = value; 
      OnPropertyChanged("Tabs"); 
     } 
    } 

    public TxtViewModel(List<TxtTabItem> items) 
    { 
     Tabs = new ObservableCollection <TxtTabItem>(); 
     foreach (var txtTabItem in items) 
     { 
      Tabs.Add(txtTabItem); 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected virtual void OnPropertyChanged(string propertyName) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

И наконец TxtTabItem класс:

public class TxtTabItem : INotifyPropertyChanged 
{ 
    public string Header { get; set; } 
    public ObservableCollection<EntryViewModel> EntryViewModels { get; set; } 

    public TxtTabItem(EntryCollection collection) 
    { 
     Header = collection.Date.ToShortDateString(); 
     EntryViewModels = new ObservableCollection <EntryViewModel>(); 
     foreach (var entry in collection.Entries) 
     { 
      EntryViewModels.Add(new EntryViewModel(entry)); 
     } 
     OnPropertyChanged("EntryViewModels"); 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

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

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

+0

Вам не хватает определений файлов и CustomButtons. Создайте новый проект и убедитесь, что он скомпилирован, и добавьте недостающее. благодаря – Dean

ответ

0

Рамка существует, но, как правило, для инициализации элементов управления к изменениям привязывается к свойству ItemsSource, а не непосредственно к DataContext.

В целом DataContext - это то, что предоставляет информацию о текущем элементе, но когда оно равно null, контекст данных родителя используется до контекста данных страницы.

Причиной этого является контекст данных, который будет содержать большой класс свойств, и привязка будет выглядеть (отражает/отражение) в DataContext для этого именованного свойства. Таким образом, используя ItemsSource, можно привязать к определенному набору элементов, при этом все еще имея DataContext полную информацию, чтобы другие элементы на элементе управления были привязаны к другим объектам.

Под MVVM, где VM или вид модели является то, что класс свойств, как уже упоминалось, установить контекст данных на страницы с этой виртуальной машины, а затем связываются с индивидуальными свойствами на различных элементов управления, которые имеют от DataContext страницы.

так

<TabControl DataContext="{Binding TextViewModel}" x:Name="tabControl" 

становится

<TabControl ItemsSource="{Binding TextViewModel}" x:Name="tabControl" 

как только вы установите контекст данных на страницы в TxtViewModel.


я обеспечиваю переплета/VM пример на моем блоге статью Xaml: ViewModel Main Page Instantiation and Loading Strategy for Easier Binding.