Настраиваемое исключение ComboBox при изменении ItemsSource - PullRequest
0 голосов
/ 24 апреля 2020

У меня есть UserControl, встраивающий ComboBox и некоторые вещи, связанные с проверкой.

Это работает, пока я не пытаюсь обновить ItemsSource (это происходит, когда я изменяю первый ComboBox "ChoixResidence"): я получаю "System. NullReferenceException: 'Ссылка на объект не установлена ​​для экземпляра объекта.' '

[EDIT] Следует отметить, что он работает с обычным ComboBox вместо ValComboBox.

Исключение при обновлении Снимок экрана ItemsSource

Я пытался установить для ItemsSource значение null, но безуспешно.

UserControl: XAML:

<UserControl
    x:Class="GestionGarages.Controls.ValComboBox"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:GestionGarages.Controls"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300"
    d:DesignWidth="400">

    <Grid>
        <StackPanel>
            <TextBlock Margin="0,0,0,5" Text="{x:Bind Title, Mode=OneWay}"/>
            <ComboBox x:Name="List"
                Width="{x:Bind Width, Mode=OneWay}"
                DisplayMemberPath="{x:Bind MemberPath, Mode=OneWay}"
                SelectedValuePath="{x:Bind ValuePath, Mode=OneWay}"
                SelectedValue="{x:Bind SelectedValue, Mode=TwoWay}">
            </ComboBox>
            <TextBlock
                x:Name="DisplayErrorMessage"
                Text="{x:Bind ErrorMessage, Mode=OneWay}"
                FontSize="10"
                Foreground="Red"
                Height="14"/>
        </StackPanel>
    </Grid>
</UserControl>

Код позади:

using System;
using System.Collections;
using System.ComponentModel;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Data;

namespace GestionGarages.Controls
{
    public sealed partial class ValComboBox : UserControl
    {
        public ValComboBox()
        {
            this.InitializeComponent();
            Loaded += ValComboBox_Loaded;
        }

        private void ValComboBox_Loaded(object sender, RoutedEventArgs e)
        {
            Binding selectedIdemBinding = new Binding
            {
                Source = this,
                Mode = BindingMode.TwoWay,
                ElementName = "SelectedItem"
            };
            List.SetBinding(ComboBox.SelectedItemProperty, selectedIdemBinding);
        }

        public IEnumerable ItemsSource
        {
            get { return (IEnumerable)GetValue(ItemsSourceProperty);  }
            set {
                SetValue(ItemsSourceProperty, value);
                List.ItemsSource = value;
            }
        }

        public static readonly DependencyProperty ItemsSourceProperty =
            DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(ValComboBox), new PropertyMetadata(null));

        public object SelectedItem
        {
            get { return (object)GetValue(SelectedItemProperty); }
            set { SetValue(SelectedItemProperty, value); List.SelectedItem = SelectedItem; }
        }

        public static readonly DependencyProperty SelectedItemProperty =
            DependencyProperty.Register("SelectedItem", typeof(object), typeof(ValComboBox), new PropertyMetadata(null));

        public string ValuePath
        {
            get { return (string)GetValue(ValuePathProperty); }
            set { SetValue(ValuePathProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ValuePath.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ValuePathProperty =
            DependencyProperty.Register("ValuePath", typeof(string), typeof(ValComboBox), new PropertyMetadata(""));

        public string MemberPath
        {
            get { return (string)GetValue(MemberPathProperty); }
            set { SetValue(MemberPathProperty, value); }
        }

        // Using a DependencyProperty as the backing store for MemberPath.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MemberPathProperty =
            DependencyProperty.Register("MemberPath", typeof(string), typeof(ValComboBox), new PropertyMetadata(""));

        public int SelectedValue
        {
            get { return (int)GetValue(SelectedValueProperty); }
            set { SetValue(SelectedValueProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Value.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SelectedValueProperty =
            DependencyProperty.Register("SelectedValue", typeof(int), typeof(ValComboBox), new PropertyMetadata(0));

        public string Title
        {
            get { return (string)GetValue(TitleProperty); }
            set { SetValue(TitleProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Title.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty TitleProperty =
            DependencyProperty.Register("Title", typeof(string), typeof(ValComboBox), new PropertyMetadata(""));

        public string ErrorMessage
        {
            get { return (string)GetValue(ErrorMessageProperty); }
            set { SetValue(ErrorMessageProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Field.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ErrorMessageProperty =
            DependencyProperty.Register("ErrorMessage", typeof(string), typeof(ValTextBox), new PropertyMetadata(""));

        public event SelectionChangedEventHandler SelectionChanged
        {
            add { List.SelectionChanged += value; }
            remove { List.SelectionChanged -= value; }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        void SetValueDp(DependencyProperty property, object value,
            [System.Runtime.CompilerServices.CallerMemberName] String p = null)
        {
            SetValue(property, value);
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(p));
        }
    }
}

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

XAML:

<ContentDialog
    x:Class="GestionGarages.Controls.AddModifContrat"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:GestionGarages.Controls"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:models="using:GestionGarages.Core.Models"
    mc:Ignorable="d"
    d:DesignHeight="1000"
    d:DesignWidth="800"
    Height="Auto"
    Width="Auto"
    Title="Ajout / Modification Contrat"
    PrimaryButtonText="OK"
    SecondaryButtonText="Annuler"
    PrimaryButtonClick="ContentDialog_PrimaryButtonClick"
    SecondaryButtonClick="ContentDialog_SecondaryButtonClick"
    Background="{ThemeResource ContentDialogBackgroundThemeBrush}"
    Foreground="{ThemeResource ContentDialogContentForegroundBrush}"
    Margin="{ThemeResource ContentDialogBorderWidth}">

    <Grid x:Name="AddModifContratGrid">
        <StackPanel Orientation="Vertical">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="200"/>
                    <ColumnDefinition Width="200"/>
                    <ColumnDefinition Width="200"/>
                    <ColumnDefinition Width="200"/>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition/>
                    <RowDefinition/>
                    <RowDefinition/>
                    <RowDefinition/>
                    <RowDefinition/>
                    <RowDefinition/>
                </Grid.RowDefinitions>
                <local:ValComboBox
                    Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"
                    x:Name="ChoixResidence"
                    Title="Résidence"
                    Width="400"
                    MemberPath="Nom"
                    ValuePath="ResidenceId"
                    SelectionChanged="ChoixResidence_SelectionChanged"
                    ErrorMessage=""/>
                <local:ValComboBox
                    Grid.Row="1" Grid.Column="0"
                    x:Name="ChoixGarage"
                    Title="Garage"
                    Width="200"
                    MemberPath="Numero"
                    ValuePath="GarageId"
                    SelectionChanged="ChoixGarage_SelectionChanged"
                    ErrorMessage=""/>
            </Grid>
        </StackPanel>
    </Grid>
</ContentDialog>

Код (часть):

private void ChoixResidence_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    Residence residence = residences.Where(g => g.ResidenceId == (int)ChoixResidence.SelectedValue).FirstOrDefault();
    garages = residence.Garages.ToList();
    ChoixGarage.ItemsSource = garages;
    ChoixGarage.SelectedItem = garages.FirstOrDefault();
}

private void ChoixGarage_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    garage = garages.Where(g => g.GarageId == (int)ChoixGarage.SelectedValue).FirstOrDefault();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...