2012-05-21 2 views
1

Я добавил диалог в мое приложение WPF. Вот Xaml:Когда привязка свойства ItemsSource генерирует элементы?

<cs:CarSystemDialog x:Class="CarSystem.CustomControls.EditHotListDialog" 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        xmlns:cs="clr-namespace:CarSystem.CustomControls" 
        DataContext="{Binding Path=HotList, RelativeSource={RelativeSource Self}}" 
        Height="265" 
        Loaded="EditHotListDialog_Loaded" 
        MaxHeight="665" 
        MaxWidth="1200" 
        SizeToContent="WidthAndHeight" 
        cs:ThemeSelector.CurrentThemeDictionary="{Binding Path=TimeOfDayTheme, RelativeSource={RelativeSource Self}}" 
        Width="850" 
        WindowStartupLocation="CenterOwner" > 

    <cs:CarSystemDialog.Resources> 
     <cs:BooleanToVisibilityConverter x:Key="BoolToVisibility" True="Visible" False="Collapsed" /> 
     <cs:CaseToVisibilityConverter x:Key="CaseToVisibilityConverter" /> 
    </cs:CarSystemDialog.Resources> 

    <Grid Background="{DynamicResource ContentBackground}" FocusManager.IsFocusScope="True" Name="LayoutRoot"> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="Auto" /> 
      <ColumnDefinition Width="*" /> 
      <ColumnDefinition Width="Auto" /> 
      <ColumnDefinition Width="*" /> 
     </Grid.ColumnDefinitions> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="Auto" /> 
      <RowDefinition Height="Auto" /> 
      <RowDefinition Height="Auto" /> 
      <RowDefinition Height="Auto" /> 
     </Grid.RowDefinitions> 

     <TextBlock FontSize="16" 
        FontWeight="Bold" 
        Foreground="{DynamicResource TextForeground}" 
        Grid.Column="0" 
        Grid.Row="0" 
        HorizontalAlignment="Right" 
        Margin="5" 
        Text="Source:" 
        VerticalAlignment="Center" /> 
     <TextBox AcceptsTab="False" 
       AcceptsReturn="False" 
       BorderBrush="{DynamicResource ControlBorder}" 
       BorderThickness="2" 
       FontSize="16" 
       FontWeight="Bold" 
       Foreground="{DynamicResource UnfocusedForeground}" 
       Grid.Column="1" 
       Grid.Row="0" 
       Margin="5" 
       MaxLength="80" 
       MaxLines="1" 
       Name="HotListNameBox" 
       TabIndex="0" 
       Text="{Binding Path=Name, Mode=TwoWay}" 
       VerticalAlignment="Center" /> 

     <TextBlock FontSize="16" 
        FontWeight="Bold" 
        Foreground="{DynamicResource TextForeground}" 
        Grid.Column="2" 
        HorizontalAlignment="Right" 
        Margin="5" 
        Text="List Type:" 
        VerticalAlignment="Center" /> 
     <ComboBox BorderBrush="{DynamicResource PlateInfoBorder}" 
        DisplayMemberPath="Value" 
        FontSize="16" 
        FontWeight="Bold" 
        Grid.Column="3" 
        ItemsSource="{Binding Path=ListTypes, RelativeSource={RelativeSource AncestorType={x:Type cs:EditHotListDialog}}}" 
        Margin="5" 
        Name="ListTypePicker" 
        SelectedValue="{Binding Path=ListTypeId, Mode=TwoWay}" 
        SelectedValuePath="Key" 
        TabIndex="1" /> 

     <TextBlock FontSize="16" 
        FontWeight="Bold" 
        Foreground="{DynamicResource TextForeground}" 
        Grid.Column="0" 
        Grid.Row="1" 
        HorizontalAlignment="Right" 
        Margin="5" 
        Text="Domain:" 
        VerticalAlignment="Center" /> 
     <ComboBox BorderBrush="{DynamicResource PlateInfoBorder}" 
        DisplayMemberPath="Value" 
        FontSize="16" 
        FontWeight="Bold" 
        Grid.Column="1" 
        Grid.Row="1" 
        ItemsSource="{Binding Path=Domains, RelativeSource={RelativeSource AncestorType={x:Type cs:EditHotListDialog}}}" 
        Margin="5" 
        Name="DomainPicker" 
        SelectedValue="{Binding Path=DomainId, Mode=TwoWay}" 
        SelectedValuePath="Key" 
        TabIndex="1" /> 

     <StackPanel Grid.Column="0" 
        Grid.ColumnSpan="4" 
        Grid.Row="2" 
        HorizontalAlignment="Center" 
        Orientation="Horizontal"> 
      <Button Background="{DynamicResource ButtonBackground}" 
        Click="OkButton_Click" 
        Content="OK" 
        FontSize="18" 
        FontWeight="Bold" 
        Foreground="{DynamicResource ButtonForeground}" 
        Height="50" 
        IsDefault="True" 
        IsEnabled="{Binding Path=CanSave, RelativeSource={RelativeSource AncestorType={x:Type cs:EditHotListDialog}}}" 
        Margin="5" 
        Name="OkButton" 
        Width="100"/> 
      <Button Background="{DynamicResource ButtonBackground}" 
        Content="Cancel" 
        FontSize="18" 
        FontWeight="Bold" 
        Foreground="{DynamicResource ButtonForeground}" 
        Height="50" 
        IsCancel="True" 
        Margin="5" 
        Name="CancelButton" 
        Width="100" /> 
     </StackPanel> 

    </Grid> 
</cs:CarSystemDialog> 

А вот код позади:

public partial class EditHotListDialog : CarSystemDialog, INotifyPropertyChanged { 

    public static readonly DependencyProperty CanSaveProperty = 
     DependencyProperty.Register("CanSave", typeof(bool), typeof(EditHotListDialog), new PropertyMetadata(false)); 

    public static readonly DependencyProperty HotListProperty = 
     DependencyProperty.Register("HotList", typeof(HotListViewModel), typeof(EditHotListDialog), 
            new PropertyMetadata(null, new PropertyChangedCallback(OnHotListChanged))); 

    public bool CanSave { 
     get { return (bool) GetValue(CanSaveProperty); } 
     set { SetValue(CanSaveProperty, value); } 
    } 

    public ObservableCollection<ItemChoice<int?>> Domains { get; set; } 

    public HotListViewModel HotList { 
     get { return (HotListViewModel) GetValue(HotListProperty); } 
     set { SetValue(HotListProperty, value); } 
     } 

    public ObservableCollection<ItemChoice<int?>> ListTypes { get; set; } 

    public EditHotListDialog() { 
     InitializeComponent(); 

     Domains = new ObservableCollection<ItemChoice<int?>>(); 
     ListTypes = new ObservableCollection<ItemChoice<int?>>(); 

     Domains .Add(new ItemChoice<int?> { Key = null, Value = "-- Pick a Domain --"}); 
     ListTypes.Add(new ItemChoice<int?> { Key = null, Value = "-- Pick a List Type --" }); 
     KeywordCache.KeywordCacheUpdated += KeywordCacheUpdated; 
    } 

    private void EditHotListDialog_Loaded(object sender, RoutedEventArgs e) { 
     UpdateChoices(); 

      DomainPicker.SelectedIndex = 0; 
     ListTypePicker.SelectedIndex = 0; 
    } 

    void HotList_PropertyChanged(object sender, PropertyChangedEventArgs e) { 
     HotListViewModel hotList = sender as HotListViewModel; 
     CanSave = !(string.IsNullOrEmpty(hotList.Name) || string.IsNullOrWhiteSpace(hotList.Name)) && hotList.ListTypeId > 0 && hotList.DomainId > 0; 
    } 

    private void OkButton_Click(object sender, RoutedEventArgs e) { 
     if (ValidateHotList()) { 
      DialogResult = true; 
      Close(); 
     } 
     e.Handled = true; 
    } 

    private void OnHotListChanged(HotListViewModel oldHotList, HotListViewModel newHotList) { 
     if (oldHotList != null) { 
      oldHotList.PropertyChanged -= HotList_PropertyChanged; 
     } 
     if (newHotList != null) { 
      newHotList.PropertyChanged += HotList_PropertyChanged; 
     } 
    } 
    private static void OnHotListChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { 
     EditHotListDialog dialog = d as EditHotListDialog; 
     dialog.OnHotListChanged(e.OldValue as HotListViewModel, e.NewValue as HotListViewModel); 
    } 

    private void UpdateChoices() { 
       . . . 
    } 

    private bool ValidateHotList() { 
     if (string.IsNullOrEmpty(HotListNameBox.Text.Trim())) { 
      CarSystemMessageBox.Show("Please enter a name for the Hot List.", "Please Name the Hot List", MessageBoxButton.OK, MessageBoxImage.None); 
      return false; 
     } 

     if (ListTypePicker.SelectedIndex <= 0) { 
      CarSystemMessageBox.Show("Please select the List Type from the drop down that specifies what type of Hot List this is.", "Please Specify a List Type", MessageBoxButton.OK, MessageBoxImage.None); 
      return false; 
     } 
     if (DomainPicker.SelectedIndex <= 0) { 
      CarSystemMessageBox.Show("Please select the Domain from the drop down that this Hot List Entry belongs to.", "Please Specify a Domain", MessageBoxButton.OK, MessageBoxImage.None); 
      return false; 
     } 
     return true; 
    } 

    #region INotifyPropertyChanged Members 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected void RaisePropertyChangedEvent(string propertyName) { 
     if (PropertyChanged != null) { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

    #endregion 
} 

}

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

Проблема в том, что после заполнения двух ObservableCollections в ComboBoxes нет Items. Когда я устанавливаю свойство SelectedIndex равным 0, ничего не выбирается. Когда диалог наконец откроется, в любом из ComboBoxes ничего не выбрано.

Я использовал этот шаблон в ряде UserControls на MainWindow моего приложения с успехом, но это первый раз, когда я использовал его в диалоговом окне. Где подходящее место для вызова метода UpdateChoices и для установки SelectedIndex свойств ComboBoxes?

P.S. Я не включил детали метода UpdateChoices, потому что это не относится к вопросу.

ответ

0

Я не знаю, что связывание было, но я избавился от него и просто установить ItemsSource свойства ComboBox управления в обработчик событий Loaded диалогового окна проблема с. Сейчас все работает.

0

Ваш DataContext установлен в HotList, который находится на том же уровне, что и свойства, к которым вы пытаетесь получить доступ. Либо измените DataContext на весь диалог, либо переместите наблюдаемые коллекции в объект HotList.

0

Проверьте шаблон MVVM. Почти никакой код не нужен, и вы получаете тестируемый код.

+0

Я знаю образец. У меня нет времени переделывать все мое приложение в шаблон MVVM прямо сейчас, так как мы должны выйти на 6/22. Однако после релиза я собираюсь потратить некоторое время на переработку экрана за раз. –

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