ItemsSource属性上的绑定何时生成Items?

时间:2012-05-21 20:27:46

标签: wpf data-binding

我在WPF应用程序中添加了一个对话框。这是Xaml:

<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之后,Items中没有ComboBoxes。当我将SelectedIndex属性设置为0时,不会选择任何内容。最后打开对话框时,在任一组合框中都没有选择任何内容。

我已经在我的应用程序UserControls上的MainWindow中使用了这个模式,但是这是我第一次在对话框中使用它。在哪里调用UpdateChoices方法并设置SelectedIndex的{​​{1}}属性的正确位置?

P.S。我没有包含UpdateChoices方法的细节,因为它与问题无关。

3 个答案:

答案 0 :(得分:0)

您的DataContext设置为HotList,它与您尝试访问的属性处于同一级别。将DataContext更改为整个对话框,或将可观察集合移动到HotList对象中。

答案 1 :(得分:0)

我不知道绑定的问题是什么,但我摆脱了它,只是在对话框的ItemsSource事件处理程序中设置ComboBox控件的Loaded属性。现在一切都有效。

答案 2 :(得分:0)

查看MVVM模式。几乎不需要代码,你可以获得可测试的代码。