Wbehning Ответов: 3

PropertyChangedEventHandler всегда null


Я не могу понять, почему PropertyChangedEventHandler всегда равен нулю. Поля со списком содержат правильные данные при загрузке элемента управления, а метод RaisePropertyChanged вызывается всякий раз, когда изменяется значение первого поля со списком, что говорит мне о том, что привязка является свойством set. Что я упускаю?



public class ModelNames : INotifyPropertyChanged
{
    // Get a list of available models by reflection
    private ObservableCollection<String> _modelList;
    private ObservableCollection<String> _modelProperties;

    public ModelNames()
    {
        SelectedModel = ModelList.FirstOrDefault();
    }

    private String _selectedModel;

    public String SelectedModel
    {
        get { return SelectedModel; }
        set
        {
            if (_selectedModel == value)
            {
                return;
            }
            _selectedModel = value;
            RaisePropertyChanged("SelectedModel");
            LoadModelResults(value);
        }
    }

    private void LoadModelResults(String modelName)
    {
        var types = GetType().Assembly.GetTypes();
        var modelType = types.FirstOrDefault(o => o.GetInterface("IModel") != null && o.Name == modelName);
        if (modelType != null)
        {
            ModelPropertyList =
                new ObservableCollection<String>(modelType.GetProperties().Select(o => o.Name).ToList());
        }

    }

    public ObservableCollection<String> ModelList
    {
        get
        {
            if (_modelList == null)
            {
                var types = GetType().Assembly.GetTypes();
                _modelList =
                    new ObservableCollection<string>(
                        types.Where(
                            o =>
                            o.GetInterface("IModel") != null && o.IsAbstract == false &&
                            o.Name.Contains("Rule") == false).Select(o => o.Name).ToList());
            }
            return _modelList;
        }
    }

    public ObservableCollection<String> ModelPropertyList
    {
        get { return _modelProperties; }
        set
        {
            if (_modelProperties == value)
            {
                return;
            }

            _modelProperties = value;
            RaisePropertyChanged("ModelPropertyList");
        }

    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void RaisePropertyChanged(String propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

код XAML:

<localView:BaseUserControl x:Class="Maximus.Pet.Views.UserControls.PetRuleBuilder"

             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:Maximus.Pet.ViewModels"

             xmlns:localView="clr-namespace:Maximus.Pet.Views.UserControls"

                           xmlns:Models="clr-namespace:Maximus.Domain.Models;assembly=Maximus.Domain" mc:Ignorable="d" 

             d:DesignHeight="300" d:DesignWidth="300">


    <Grid removed="#814678AA" >

        <ComboBox ItemsSource="{Binding ModelNames}" SelectedItem="{Binding Path=SelectedModel,Mode=TwoWay}"

                Height="23" HorizontalAlignment="Left" Margin="44,27,0,0" Name="comboBoxModelNames" VerticalAlignment="Top" Width="120" 

                   SelectionChanged="comboBoxModelNames_SelectionChanged" d:DataContext="{d:DesignData }" />

        <ComboBox ItemsSource="{Binding ModelProperties}"

                Height="23" HorizontalAlignment="Left" Margin="44,57,0,0" Name="comboBoxModelProperties" VerticalAlignment="Top" Width="120" />

        

    </Grid>

</localView:BaseUserControl>


с фоновым кодом:

 private readonly PetRulesViewModel _petRulesViewModel;
public PetRuleBuilder()
        {
            InitializeComponent();

            _petRulesViewModel = new PetRulesViewModel();
            
            DataContext = _petRulesViewModel;
        }

3 Ответов

Рейтинг:
2

Graeme_Grant

Оно делает работай, только не так, как тебе хочется... например:

<Window.DataContext>
    PetRulesViewModel
</Window.DataContext>

Вы можете задать его таким образом в любой точке дерева XAML, но чем глубже вы его зададите, тем более сфокусированным он будет. Это только вперед. ie: все вышеперечисленные узлы не получат видимости для набора DataConext.


Рейтинг:
0

Sergey Alexandrovich Kryukov

Это происходит потому, что вы никогда не добавляете обработчик в список вызовов этого события. Это можно сделать либо с помощью оператора "+=" в коде C#, либо в XAML. Я не вижу ничего подобного в вашем коде, ни в той части, которую вы показываете. Я серьезно подозреваю, что ты никогда этого не делал.

Этот пример MSDN даст вам самую основную идею:
http://msdn.microsoft.com/en-us/library/ms743596.aspx[^].

Однако я почти всегда использую анонимный метод и, С.NET V. 3.5 или выше, лямбда-синтаксис:

SomeEvent += (sender, eventArgs) => { SomeCode(); }


Для этого есть целый ряд веских причин.

—СА


Wbehning

Я думал, что вся эта идея
WPF, Observablecollections и INotifyPropertyChanged заключались в том, что вам не нужно было проходить через все это. У меня есть и другие реализации, где это действительно работает. Я просто не работаю для этого конкретного Veiw, ViewModel и Model.

Рейтинг:
0

WilllllChen

Столкнувшись с той же проблемой,я наконец выяснил, что datacontext, установленный в файле .xaml, не работает(пока не знаю почему).Но когда я установить свойство DataContext страницы в фоновом режиме .файл CS
любить:

this.datacontext = xxxx;


и событие PropertyChangedEventHandler obejct больше не является нулевым!