Как привязать Observable Collection к ListView

Я настроил привязку ListView, следуя этому примеру, привязка к наблюдаемой коллекции, но когда я запускаю приложение, значения коллекции не отображаются в ListView.

Окно вывода не выдает никаких ошибок привязки, поэтому не уверен, в чем может быть ошибка привязки. Также я установил точку останова в списке перед его отправкой на вторую виртуальную машину, и он заполнен, т. е. не равен нулю.

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

Может ли кто-нибудь посоветовать, как отладить пустой ListView?

Это привязка, установленная в представлении:

<ListBox ItemsSource="{Binding AddedSubjectGradePairsCopy}" Height="400" Margin="0,0,0,-329" VerticalAlignment="Top">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <TextBlock>
                        <Run Text="{Binding Subject}" /><Run Text=" - " /><Run Text="{Binding Points}" />
                        </TextBlock>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

Контекст данных для представления устанавливается следующим образом в коде:

namespace LC_Points.View
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class ViewSubjectGradePage : Page
    {
        private NavigationHelper navigationHelper;

        private ViewSubjectGradeViewModel ViewModel;

        public ViewSubjectGradePage()
        {
            this.InitializeComponent();

            this.navigationHelper = new NavigationHelper(this);
            this.navigationHelper.LoadState += this.NavigationHelper_LoadState;
            this.navigationHelper.SaveState += this.NavigationHelper_SaveState;

            ViewModel = new ViewSubjectGradeViewModel();
            this.DataContext = ViewModel;
        }

        /// <summary>
        /// Gets the <see cref="NavigationHelper"/> associated with this <see cref="Page"/>.
        /// </summary>
        public NavigationHelper NavigationHelper
        {
            get { return this.navigationHelper; }
        }


        /// <summary>
        /// Populates the page with content passed during navigation.  Any saved state is also
        /// provided when recreating a page from a prior session.
        /// </summary>
        /// <param name="sender">
        /// The source of the event; typically <see cref="NavigationHelper"/>
        /// </param>
        /// <param name="e">Event data that provides both the navigation parameter passed to
        /// <see cref="Frame.Navigate(Type, Object)"/> when this page was initially requested and
        /// a dictionary of state preserved by this page during an earlier
        /// session.  The state will be null the first time a page is visited.</param>
        private void NavigationHelper_LoadState(object sender, LoadStateEventArgs e)
        {
        }

        /// <summary>
        /// Preserves state associated with this page in case the application is suspended or the
        /// page is discarded from the navigation cache.  Values must conform to the serialization
        /// requirements of <see cref="SuspensionManager.SessionState"/>.
        /// </summary>
        /// <param name="sender">The source of the event; typically <see cref="NavigationHelper"/></param>
        /// <param name="e">Event data that provides an empty dictionary to be populated with
        /// serializable state.</param>
        private void NavigationHelper_SaveState(object sender, SaveStateEventArgs e)
        {
        }

        #region NavigationHelper registration

        /// <summary>
        /// The methods provided in this section are simply used to allow
        /// NavigationHelper to respond to the page's navigation methods.
        /// <para>
        /// Page specific logic should be placed in event handlers for the  
        /// <see cref="NavigationHelper.LoadState"/>
        /// and <see cref="NavigationHelper.SaveState"/>.
        /// The navigation parameter is available in the LoadState method 
        /// in addition to page state preserved during an earlier session.
        /// </para>
        /// </summary>
        /// <param name="e">Provides data for navigation methods and event
        /// handlers that cannot cancel the navigation request.</param>
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            this.navigationHelper.OnNavigatedTo(e);
        }

        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            this.navigationHelper.OnNavigatedFrom(e);
        }

        #endregion
    }
}

И получение списка в ViewSubjectGradeVM через конструктор:

namespace LC_Points.ViewModel
{
    public class ViewSubjectGradeViewModel 
    {


        public ViewSubjectGradeViewModel()
        {


        }

         /// <summary>
        /// Initializes a new instance of the ViewSubjectGradeViewModel class.
        /// </summary>
        public ViewSubjectGradeViewModel(IEnumerable<ScoreModel> addedSubjectGradePairs)
        {
            this.AddedSubjectGradePairsCopy = addedSubjectGradePairs;

        }


        //Property for collection passed from MainViewModel
        public IEnumerable<ScoreModel> AddedSubjectGradePairsCopy { get; set; }


    }
}

И это модель поддержки для списка, передаваемого из MainVM в ViewSubjectGradeVM:

namespace LC_Points.Model
{
    public class ScoreModel : INotifyPropertyChanged
    {

        // The name of the subject.
        public string Subject { get; set; }


        // The points paired with each grade type.
        public int Points { get; set; }


        public event PropertyChangedEventHandler PropertyChanged;

        private void RaisePropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }


    }
}

person Brian J    schedule 23.05.2015    source источник
comment
Где вы устанавливаете DataContext?   -  person Hamlet Hakobyan    schedule 24.05.2015
comment
Я установил контекст данных в коде представления, сейчас опубликую редактирование.   -  person Brian J    schedule 24.05.2015
comment
Да, но вы вызываете ctor по умолчанию, поэтому AddedSubjectGradePairsCopy равно нулю.   -  person Hamlet Hakobyan    schedule 24.05.2015
comment
Хорошо, теперь я вижу это, мне просто нужно избавиться от этого тогда? hastebin.com/oretezoqot.cs   -  person Brian J    schedule 24.05.2015
comment
Нет, я удалил конструктор по умолчанию, но ListView по-прежнему не показывает никакого содержимого, какие-либо другие идеи?   -  person Brian J    schedule 24.05.2015
comment
Вы не должны удалять ctor по умолчанию. Вам нужно что-то вроде этого ViewModel = new ViewSubjectGradeViewModel(GetScoreModels()); this.DataContext = ViewModel; вместо ViewModel = new ViewSubjectGradeViewModel(); this.DataContext = ViewModel;   -  person Hamlet Hakobyan    schedule 24.05.2015
comment
Итак, я думаю, что понял, к чему вы клоните, мне нужно указать параметр, который принимает мой ViewSubjectGradeViewModel. Я пробовал следующее, но мне пишет hastebin.com/ohihameyos.tex, и это моя попытка : gist.github.com/BrianJVarley/87a051d400ea1c7ffcfb   -  person Brian J    schedule 25.05.2015


Ответы (1)


Попробуйте что-нибудь вроде этого. Конечно, ваша модель должна исходить из какого-то источника, который вы должны сопоставить с вашей моделью представления. Но это иллюстрирует вам способ установить правильный контекст данных.

var scoremodels = new List<ScoreModel>
{
    new ScoreModel {Subject = "Subj1", Points = 6},
    new ScoreModel {Subject = "Subj2", Points = 3},
    new ScoreModel {Subject = "Subj3", Points = 8},
}
ViewModel = new ViewSubjectGradeViewModel(scoreModels);
this.DataContext = ViewModel;
person Hamlet Hakobyan    schedule 24.05.2015
comment
Хорошо, если я правильно понимаю, я должен определить то, что передается от MainVM к этой VM. Но когда я пытаюсь сделать следующее в коде ViewSubjectGradePage, компилятор сообщает мне, что список не существует в текущем контексте. ` ViewModel = new ViewSubjectGradeViewModel (AddedSubjectGradePairs); ` AddedSubjectGradePairs — это список, передаваемый из MainVM, составленный из ScoreModel. - person Brian J; 25.05.2015
comment
Что вы пробовали? Показать код ViewSubjectGradePage. - person Hamlet Hakobyan; 27.05.2015
comment
Это то, что я пробовал, но компилятор говорит мне, что список не существует в текущем контексте, что верно, поскольку список находится в моей MainVM. Список представляет собой наблюдаемую коллекцию типа ScoreModel, которая является моей моделью данных. Мой код ViewSubjectGradePage: gist.github.com/BrianJVarley/87a051d400ea1c7ffcfb, и это главная виртуальная машина, на которой Я передаю список на виртуальную машину этой страницы в viewGradesCommand RelayCommand: /а> - person Brian J; 27.05.2015
comment
Я не видел, где вы создали MainViewModel. Также AddedSubjectGradePairs недоступен из ViewSubjectGradePage. - person Hamlet Hakobyan; 27.05.2015
comment
Это MainViewModel, где список создается и передается на другую виртуальную машину: hastebin.com/alirebanup.cs - person Brian J; 01.06.2015
comment
Ваша коллекция пуста. AddedSubjectGradePairs = new ObservableCollection<ScoreModel>(); - person Hamlet Hakobyan; 01.06.2015
comment
Коллекция не пуста после того, как я добавляю в нее пары при вызове команды AddGrade. - person Brian J; 02.06.2015
comment
ViewSubjectGradeViewModel subjectGradeObj = new ViewSubjectGradeViewModel(AddedSubjectGradePairs); Эта строка кода не имеет значения, поскольку вы потеряли ссылку на subjectGradeObj. - person Hamlet Hakobyan; 02.06.2015