2015-09-16 2 views
3

Я пытаюсь связать кучу пользовательских элементов управления с WPF-приложением. Идея - это viewmodel содержит список имен серверов, передает их на ObservableCollection, а затем коллекция привязана к главному окну.WPF Непредвиденное поведение привязки ObservableCollection to UserControl

Когда в режиме разработки все работает отлично! Однако, когда я запускаю приложение, привязка, похоже, ломается, и я затрудняюсь объяснить, почему.

enter image description here

Это XAML для пользовательского элемента управления:

<UserControl x:Class="ServerMonitor.Wpf.ServerControl" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:local="clr-namespace:ServerMonitor.Wpf" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"> 
    <UserControl.DataContext> 
     <local:Server /> 
    </UserControl.DataContext> 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="Auto" /> 
      <RowDefinition Height="Auto" /> 
      <RowDefinition Height="Auto" /> 
      <RowDefinition Height="Auto" /> 
      <RowDefinition Height="Auto" /> 
      <RowDefinition Height="Auto" /> 
      <RowDefinition Height="Auto" /> 
      <RowDefinition Height="Auto" /> 
      <RowDefinition Height="Auto" /> 
     </Grid.RowDefinitions> 

     <Grid.Resources> 
      <Style TargetType="{x:Type TextBlock}"> 
       <Setter Property="TextAlignment" Value="Center" /> 
       <Setter Property="HorizontalAlignment" Value="Stretch" /> 
      </Style> 
     </Grid.Resources> 

     <TextBlock Grid.Row="0" Text="{Binding Name}" /> 

     <TextBlock Grid.Row="8" Text="{Binding LastPolled}" /> 
    </Grid> 
</UserControl> 

Это вид модели (ViewModelBase является абстрактным классом, который реализует INotifyPropertyChanged):

public class MainWindowViewModel : ViewModelBase { 

    private List<string> _MachineNames = new List<string> { 
     "wschampad", 
     // Test 
     "T009", "T010", "T011", "T012", 
    }; 
    public List<string> MachineNames { 
     get { return _MachineNames; } 
     set { _MachineNames = value; OnPropertyChanged("ManchineNames"); } 
    } 

    private ObservableCollection<Server> _Servers; 
    public ObservableCollection<Server> Servers { 
     get { 
      if (_Servers == null) { 
       _Servers = new ObservableCollection<Server>(); 
       foreach (var machine in MachineNames) { 
        _Servers.Add(new Server { 
         Name = machine, 
         LastPolled = DateTime.Now, 
        }); 
       } 
       OnPropertyChanged("Servers"); 
      } 

      return _Servers; 
     } 
     set { _Servers = value; OnPropertyChanged("Servers"); } 
    } 
} 

И это является основным окном XAML:

<Window x:Class="ServerMonitor.Wpf.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:ServerMonitor.Wpf" 
     Title="Leading Hedge Server Monitor" Height="350" Width="800"> 
    <Window.DataContext> 
     <local:MainWindowViewModel /> 
    </Window.DataContext> 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="Auto" /> 
      <RowDefinition Height="Auto" /> 
      <RowDefinition Height="*" /> 
      <RowDefinition Height="Auto" /> 
     </Grid.RowDefinitions> 

     <Menu Grid.Row="0"> 
      <MenuItem Header="_File"> 
       <MenuItem Header="_Exit" Name="MenuFileExit" Click="MenuFileExit_Click" /> 

      </MenuItem> 
      <MenuItem Header="_Edit"> 
       <MenuItem Header="_Options" Name="MenuEditOptions" IsEnabled="False" /> 
      </MenuItem> 
      <MenuItem Header="_Help"> 
       <MenuItem Header="_About" Name="MenuHelpAbout" IsEnabled="False" /> 
      </MenuItem> 
     </Menu> 

     <ItemsControl Grid.Row="1" ItemsSource="{Binding Servers}"> 
      <ItemsControl.ItemsPanel> 
       <ItemsPanelTemplate> 
        <WrapPanel /> 
       </ItemsPanelTemplate> 
      </ItemsControl.ItemsPanel> 
      <ItemsControl.ItemTemplate> 
       <DataTemplate> 
        <Border BorderBrush="Black" BorderThickness="1" Margin="5,5,5,5"> 
         <local:ServerControl DataContext="{Binding}" /> 
        </Border> 
       </DataTemplate> 
      </ItemsControl.ItemTemplate> 
     </ItemsControl> 

    </Grid> 
</Window> 

EDIT

Изменение DataContext в UserControl в игнорируемые работал, чтобы исправить этот вопрос!

<UserControl x:Class="ServerMonitor.Wpf.ServerControl" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:local="clr-namespace:ServerMonitor.Wpf" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"> 
    <d:UserControl.DataContext> 
     <local:Server /> 
    </d:UserControl.DataContext> 

ответ

3

Избавиться от этого в вашем UserControl:

<UserControl.DataContext> 
    <local:Server /> 
</UserControl.DataContext> 

Это переписав DataContext вы передаете ему из ItemTemplate, и вы в конечном итоге со значениями по умолчанию для DateTime и string.

+0

Это сработало! Однако я немного изменил это, так что я мог сохранить intellisense.

+0

Да, я собирался добавить, что если вы сказали, что хотите, чтобы помощь IntelliSense по-прежнему была :) – Kcvin

+0

Спасибо за помощь в этом , Мне никогда не приходило в голову, что привязка контроля будет иметь приоритет. –

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