locked
Не выводятся данные в листбокс на третьей странице подряд RRS feed

  • Вопрос

  • Здравствуйте.

    Проблема следующая:

    Работаю с локальной базой данных. На первой странице в листбокс вывожу список категорий так:

    <ListBox x:Name="CategoryListBox" Margin="0,4,0,1" ItemsSource="{Binding Categories}" SelectionChanged="CategoryListBox_SelectionChanged">
                            <ListBox.ItemTemplate>
                                <DataTemplate>
                                    <StackPanel>
                                        <TextBlock
                                        Text="{Binding Name_category}"
                                        Style="{StaticResource PhoneTextLargeStyle}" />
                                    </StackPanel>
                                </DataTemplate>
                            </ListBox.ItemTemplate>
                        </ListBox>

    По нажатию на одну из категорий открывается список акций из этой категории. Список акций выводится по тому же принципу.  И категории, и акции заданы во ViewModel.

            public void LoadCollectionsFromDatabase()
            {
                var CategoriesInDB = from Category category in MyDB21.Categories
                                     select category;
    
                Categories = new ObservableCollection<Category>(CategoriesInDB);
    
                var ActionsInDB = from Action аction in MyDB21.Actions
                                  select аction;
    
                Actions = new ObservableCollection<Action>(ActionsInDB);
            }

    На второй странице, т.е. там, где список акций (с выводом на экран которого проблем никаких), в строку заголовка выводится название категории.

    <TextBlock x:Name="PageTitle" Text="{Binding Name_category}" ...

    Название категории выводится, но вот такая строчка выдается в обработчике:

    System.Windows.Data Error: BindingExpression path error: 'Name_category' property not found on 'VseSkidki.VseSkidkiViewModel' 'VseSkidki.VseSkidkiViewModel' (HashCode=120571837). BindingExpression: Path='Name_category' DataItem='VseSkidki.VseSkidkiViewModel' (HashCode=120571837); target element is 'System.Windows.Controls.TextBlock' (Name='PageTitle'); target property is 'Text' (type 'System.String')..

    Не обращал бы внимания ибо все равно выводится, но третья страница, где должно содержаться описание акции, пуста. У листобокса  ItemsSource="{Binding Actions}". ID передается, проверял. Пишет следующее:

    System.Windows.Data Error: BindingExpression path error: 'Actions' property not found on 'VseSkidki.Action' 'VseSkidki.Action' (HashCode=120570973). BindingExpression: Path='Actions' DataItem='VseSkidki.Action' (HashCode=120570973); target element is 'System.Windows.Controls.ListBox' (Name='AInfoListBox'); target property is 'ItemsSource' (type 'System.Collections.IEnumerable')..

    Как быть и что делать? Кажется, что разгадка проста, но не включусь никак.

    Заранее спасибо.

    UPD. Код получения и присвоения ID акции:

    public AInfo()
            {
                InitializeComponent();
                this.DataContext = App.ViewModel;
            }
    
    protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
            {
                long? entityID = long.Parse(NavigationContext.QueryString["currID"]);
                DataContext = App.ViewModel.Actions.FirstOrDefault<Action>(action => action.Id_action == entityID);
    
                base.OnNavigatedTo(e);
            }

    • Изменено Fat.Hansmer 20 февраля 2013 г. 10:37
    13 февраля 2013 г. 18:09

Ответы

  • Так, давайте с самого начала еще раз - на это странице вы хотите детальную информацию отобразить о всех Action или об одном конкретном?

    Если о всех - то оставьет DataContext = App.ViewModel и не изменяйте ничего в xaml.

    Если об одном конктретном - то сделайте отдельный класс ViewModel3 для этого случая, в котором задайте один единственный Action:

        public class ViewModel3
        {
            public List<Action> Actions { get; private set; }
    
            public ViewModel3(Action action)
            {
                Actions = new List<Action>();
                Actions.Add(action);
            }
        }

    При переходе на страницу:
       long? entityID = long.Parse(NavigationContext.QueryString["currID"]);
       Action action = App.ViewModel.Actions.FirstOrDefault<Action>(action => action.Id_action == entityID);
       DataContext = new ViewModel3(action);


    Для связи [mail]

    • Помечено в качестве ответа Fat.Hansmer 20 февраля 2013 г. 16:17
    20 февраля 2013 г. 14:31
  • Спасибо большое за ответ, но прежде чем я его увидел, я решил вместо листбокса ScrollViewer сделать и убрать все template.

    <ScrollViewer x:Name="AInfoScroll" Margin="0,0,0,0">
                    <StackPanel>
                                <TextBlock
                                        Text="{Binding Name_action}" TextWrapping="Wrap" Style="{StaticResource PhoneTextLargeStyle}" />
                                <TextBlock
                                        Text="{Binding Action_descr_full}" TextWrapping="Wrap" Style="{StaticResource PhoneTextLargeStyle}" />
                                <TextBlock
                                        Text="{Binding Date_stop}" TextWrapping="Wrap" Style="{StaticResource PhoneTextLargeStyle}" />
                            </StackPanel>
                </ScrollViewer>

    И получилось то, что я хотел. Да, нужно было конкретную акцию выводить. Неча было опять всё в листбокс пихать - все проблемы от полного отсутствия опыта.

    Еще раз спасибо)




    • Помечено в качестве ответа Fat.Hansmer 20 февраля 2013 г. 16:17
    • Изменено Fat.Hansmer 20 февраля 2013 г. 21:08
    20 февраля 2013 г. 16:17

Все ответы

  • Проверьте чтобы все было публичным, а не приватным это касается и коллекции Actions и Name_category. Ошибки должны пропасть
    14 февраля 2013 г. 12:51
  • Все публично вроде. Список категорий на первой странице выводится, список акций на второй - тоже. В чем может быть косяк с информацией об акции? Там же используется та же самая коллекция. Все вроде единообразно, ан почему-то не хочет... Какая-то закономерность: если коллекция используется на одной странице, то на следующей на нее ругается, мол, не знаю такой.
    • Изменено Fat.Hansmer 14 февраля 2013 г. 17:53
    14 февраля 2013 г. 15:01
  • Вы можете показать код класса Actions, а также класса Category?!
    14 февраля 2013 г. 18:48
  • Так во ViewModel:

    private ObservableCollection<Category> _Categories; public ObservableCollection<Category> Categories { get { return _Categories; } set { if (_Categories != value) { _Categories = value; NotifyPropertyChanged("Categories"); } } } private ObservableCollection<Action> _Actions; public ObservableCollection<Action> Actions { get { return _Actions; } set { if (_Actions != value) { _Actions = value; NotifyPropertyChanged("Actions"); } } } public void LoadCollectionsFromDatabase() { var CategoriesInDB = from Category category in MyDB21.Categories select category; Categories = new ObservableCollection<Category>(CategoriesInDB); var ActionsInDB = from Action аction in MyDB21.Actions select аction; Actions = new ObservableCollection<Action>(ActionsInDB);

    }

    Так в DataContext:

    public Table<Action> Actions { get { return this.GetTable<Action>(); } } public Table<Category> Categories { get { return this.GetTable<Category>(); } }

    и

    [Table()]
    public partial class Category : INotifyPropertyChanging, INotifyPropertyChanged
    {...}

    ...

    [Table()]
    public partial class Action : INotifyPropertyChanging, INotifyPropertyChanged
    {...}

    И на всякий: так в xaml в списке акций (повторюсь - работает):

    <ListBox x:Name="ActionsOfCategoryListBox" Margin="0,4,0,1" Height="602" ItemsSource="{Binding Actions}">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <StackPanel>
                                <TextBlock
                                        Text="{Binding Name_action}"
                                        Style="{StaticResource PhoneTextLargeStyle}" />
                            </StackPanel>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>

    А так в xaml в инфо об акции:

    <ListBox x:Name="AInfoListBox" Margin="0,4,0,1" Height="602" ItemsSource="{Binding Actions}">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <StackPanel>
                                <TextBlock
                                        Text="{Binding Name_action}"
                                        Style="{StaticResource PhoneTextLargeStyle}" />
    <TextBlock
                                        Text="{Binding Action_descr_full}"
                                        Style="{StaticResource PhoneTextLargeStyle}" />
                            </StackPanel>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>


    • Изменено Fat.Hansmer 15 февраля 2013 г. 12:54
    15 февраля 2013 г. 12:41
  • Это все хорошо. Но я имел ввиду именно классы Action и Category, где вы указываете их свойства

    Для вашего случая должно быть так:

    public class Category
    {
      public string Name_category {get; set;}
    }

    public class Action { public string Name_action {get; set;}

    public string Action_descr_full {get; set;} }

    А у вас скорее всего стоит private у Name_category и у Action

    15 февраля 2013 г. 13:20
  • Если бы не было пабликов, не выводилось бы ничего на первых двух страницах, я правильно мыслю?

    public ObservableCollection<Action> Actions обращается к таблице return _Actions; 

    а там и 

    [Table()] public partial class Action : INotifyPropertyChanging, INotifyPropertyChanged

    и все колонки по такому принципу

    [Column(Name = "name_action", Storage = "_Name_action", DbType = "NVarChar(2000) NOT NULL", CanBeNull = false)]
            public string Name_action
            {
                get
                {
                    return this._Name_action;
                }
                set
                {
                    if ((this._Name_action != value))
                    {
                        this.OnName_actionChanging(value);
                        this.SendPropertyChanging();
                        this._Name_action = value;
                        this.SendPropertyChanged("Name_action");
                        this.OnName_actionChanged();
                    }
                }
            }

    Кстати, ругаться ругается, но если попробовать выводить в заголовок страницы Binding=Name_action, то оно выводится.


    • Изменено Fat.Hansmer 15 февраля 2013 г. 16:15
    15 февраля 2013 г. 16:07
  • Блин, нашел ответ. Не знаю почему, но содержимое не хочет показваться внутри листбокса (у которого я уже и binding тёр и чего только не делал), а если просто указать текстблоки внутри contentpanel, то все выводится.

    Может тогда подскажете как его вылечить, или есть альтернатива какая-нить?


    • Изменено Fat.Hansmer 15 февраля 2013 г. 16:23
    15 февраля 2013 г. 16:23
  • Пардон, что-то не заметил, что вы это в первый раз указали. Сам я с подобной реализацией не работал написал вам про приватность исключительно из-за того что встречал такую же ошибку, теперь по делу в этой статье написано:

    « Ключевое слово partial указывает на то, что другие части класса, структуры или интерфейса могут быть определены в пространстве имен. partial. Для формирования окончательного типа все части должны быть доступны во время компиляции. Все части должны иметь одинаковые специальные возможности, например, publicprivate и т.д.» 


    Поэтому попробуйте поставить partial при объявлении всех колонок. Может быть проблема в этом.




    • Изменено ProstoKorol 15 февраля 2013 г. 17:47
    15 февраля 2013 г. 17:43
  • Не обращал бы внимания ибо все равно выводится, но третья страница, где должно содержаться описание акции, пуста. У листобокса  ItemsSource="{Binding Actions}". ID передается, проверял. Пишет следующее:

    System.Windows.Data Error: BindingExpression path error: 'Actions' property not found on 'VseSkidki.Action' 'VseSkidki.Action' (HashCode=120570973). BindingExpression: Path='Actions' DataItem='VseSkidki.Action' (HashCode=120570973); target element is 'System.Windows.Controls.ListBox' (Name='AInfoListBox'); target property is 'ItemsSource' (type 'System.Collections.IEnumerable')..

    Как быть и что делать? Кажется, что разгадка проста, но не включусь никак.

    Заранее спасибо.

    Привет

    А DataContext вы устанавливаете для ListBox на вашей 3-ей странице? И устанавливаете ли правильно? А то судя по ошибке у вас DataContext это объект класса VseSkidki.Action, у которого привязка потом пытается искать свойство Actions. Проверьте еще раз, что DataContext для ListBox устанавливается на верный ViewModel


    Для связи [mail]

    18 февраля 2013 г. 7:54
  • Да, кинулся в пространные объяснения, а самую суть не показал. 

    В коде передается и присваивается ID, больше ничего нет:

    public AInfo() { InitializeComponent(); this.DataContext = App.ViewModel; }

    protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) { long? entityID = long.Parse(NavigationContext.QueryString["currID"]); DataContext = App.ViewModel.Actions.FirstOrDefault<Action>(action => action.Id_action == entityID); base.OnNavigatedTo(e); }

    Видимо, в строке присваивания и устанавливается не тот DataContext, причем ко всей странице.

    Подскажите, пожалуйста, как сделать по-другому.





    • Изменено Fat.Hansmer 19 февраля 2013 г. 22:41
    18 февраля 2013 г. 14:13
  • Так, значит у вас проблемы в xaml разметке на 3ьей странице, для чего у вас там listBox если нужно вывести только лишь подробную информацию о ранее выбранном Action. У вас же внутри этого класса нет данных, которые выводить в листбокс надо.

    Вам нужно просто определить TextBlock-и у которых задать привязку на свойства Action - Name_action, Action_descr_full и тд. А DataContext задается верно

    Для связи [mail]


    20 февраля 2013 г. 11:37
  • На этой странице планирую выводить много информации, вся она не уместится на экране. Поэтому нужен листбокс, чтобы листалось. Или есть другой вариант?

    Разметка без изысков пока:

    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
                <ListBox x:Name="AInfoListBox" Margin="0,0,0,0" ItemsSource="{Binding Actions}">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <StackPanel>
                                <TextBlock
                                        Text="{Binding Name_action}" TextWrapping="Wrap" Style="{StaticResource PhoneTextLargeStyle}" />
                                <TextBlock
                                        Text="{Binding Action_descr_full}" TextWrapping="Wrap" Style="{StaticResource PhoneTextLargeStyle}" />
                                <TextBlock
                                        Text="{Binding Date_stop}" TextWrapping="Wrap" Style="{StaticResource PhoneTextLargeStyle}" />
                            </StackPanel>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
            </Grid>
        </Grid>




    • Изменено Fat.Hansmer 20 февраля 2013 г. 13:49
    20 февраля 2013 г. 13:40
  • Так, давайте с самого начала еще раз - на это странице вы хотите детальную информацию отобразить о всех Action или об одном конкретном?

    Если о всех - то оставьет DataContext = App.ViewModel и не изменяйте ничего в xaml.

    Если об одном конктретном - то сделайте отдельный класс ViewModel3 для этого случая, в котором задайте один единственный Action:

        public class ViewModel3
        {
            public List<Action> Actions { get; private set; }
    
            public ViewModel3(Action action)
            {
                Actions = new List<Action>();
                Actions.Add(action);
            }
        }

    При переходе на страницу:
       long? entityID = long.Parse(NavigationContext.QueryString["currID"]);
       Action action = App.ViewModel.Actions.FirstOrDefault<Action>(action => action.Id_action == entityID);
       DataContext = new ViewModel3(action);


    Для связи [mail]

    • Помечено в качестве ответа Fat.Hansmer 20 февраля 2013 г. 16:17
    20 февраля 2013 г. 14:31
  • Спасибо большое за ответ, но прежде чем я его увидел, я решил вместо листбокса ScrollViewer сделать и убрать все template.

    <ScrollViewer x:Name="AInfoScroll" Margin="0,0,0,0">
                    <StackPanel>
                                <TextBlock
                                        Text="{Binding Name_action}" TextWrapping="Wrap" Style="{StaticResource PhoneTextLargeStyle}" />
                                <TextBlock
                                        Text="{Binding Action_descr_full}" TextWrapping="Wrap" Style="{StaticResource PhoneTextLargeStyle}" />
                                <TextBlock
                                        Text="{Binding Date_stop}" TextWrapping="Wrap" Style="{StaticResource PhoneTextLargeStyle}" />
                            </StackPanel>
                </ScrollViewer>

    И получилось то, что я хотел. Да, нужно было конкретную акцию выводить. Неча было опять всё в листбокс пихать - все проблемы от полного отсутствия опыта.

    Еще раз спасибо)




    • Помечено в качестве ответа Fat.Hansmer 20 февраля 2013 г. 16:17
    • Изменено Fat.Hansmer 20 февраля 2013 г. 21:08
    20 февраля 2013 г. 16:17
  • Это было правильное решение - выбрать ScrollViewer, ListBox был излишним

    Для связи [mail]

    20 февраля 2013 г. 21:51