связать viewmodel для просмотра

#c# #silverlight #windows-phone-7

#c# #silverlight #windows-phone-7

Вопрос:

Я не могу заставить свой xaml привязываться к моей viewmodel. У меня в моей ViewModel есть ObservableCollection класса INotifyPropertyChanged, который содержит данные о получателе. Вот мой класс Recepie :

 namespace WP7SQLiteClient.Model
{
    public class MainViewModelItem : INotifyPropertyChanged
    {
        string _title, _subTitle, _imageUriPath;

        string title
        {

            get
            {
                return _title;
            }
            set
            {
                _title = value;
                NotifyPropertyChanged("title");
            }
        }
        string subTitle
        {
            get
            {
                return _subTitle;
            }
            set
            {
                _subTitle = value;
                NotifyPropertyChanged("subTitle");
            }
        }
        string imageUriPath
        {
            get
            {
                return _imageUriPath;
            }
            set
            {
                _imageUriPath = value;
                NotifyPropertyChanged("imageUriPath");
            }
        }

        public MainViewModelItem(string title, string subtitle, string imageuripath)
        {
            this.title = title;
            this.subTitle = subtitle;
            this.imageUriPath = imageuripath;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
    }
}
 

И моя ViewModel, которая содержит список получателей :

 namespace WP7SQLiteClient.ViewModel
{

        public class PanoramaViewModel : INotifyPropertyChanged
        {
            public ObservableCollection<MainViewModelItem> _recepiesList;


            public ObservableCollection<MainViewModelItem> recepiesList
            {
                get
                {
                    return _recepiesList;
                }

                set
                {
                    _recepiesList = value;
                    NotifyPropertyChanged("recepiesList");
                }
            }

            public PanoramaViewModel()
            {
                this.recepiesList = new ObservableCollection<MainViewModelItem>();

            }

            public bool IsDataLoaded
            {
                get;
                private set;
            }

            public void LoadData()
            {
                this.recepiesList.Add(new MainViewModelItem("Classics", "", ""));
                this.recepiesList.Add(new MainViewModelItem("Perfect Pasta", "", ""));
                this.recepiesList.Add(new MainViewModelItem("Favorites", "", ""));
                this.recepiesList.Add(new MainViewModelItem("Snacks amp; Antipasti", "", ""));
                this.recepiesList.Add(new MainViewModelItem("Desserts", "", ""));
                this.recepiesList.Add(new MainViewModelItem("3 minutes recipes", "", ""));

                this.IsDataLoaded = true;
            }


            private string _sampleProperty = "Sample Runtime Property Value";
            /// <summary>
            /// Sample ViewModel property; this property is used in the view to display its value using a Binding
            /// </summary>
            /// <returns></returns>
            public string SampleProperty
            {
                get
                {
                    return _sampleProperty;
                }
                set
                {
                    if (value != _sampleProperty)
                    {
                        _sampleProperty = value;
                        NotifyPropertyChanged("SampleProperty");
                    }
                }
            }




            public event PropertyChangedEventHandler PropertyChanged;

            protected void NotifyPropertyChanged(String info)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(info));
                }
            }
        }

}
 

В моем файле MainPage.xaml (он находится в корне проекта, ViewModel находится в папке ViewModel, а модель — в папке Model) у меня есть список, объявленный следующим образом :

 <ListBox x:Name="recepiesList"  ItemTemplate="{StaticResource ListViewModelTemplate}" > 

                </ListBox>
 

Шаблон находится в App.xaml и, безусловно, верен. Он использует такие вещи, как {Binding title}

В MainPage.cs я пытаюсь связать модель представления со страницей, используя :

 public static PanoramaViewModel viewModel = null;

        public static PanoramaViewModel ViewModel
        {
            get
            {
                // Delay creation of the view model until necessary
                if (viewModel == null)
                    viewModel = new PanoramaViewModel();

                return viewModel;
            }
        } 
public MainPage()
        {

            InitializeComponent();

            ViewModel.LoadData();
            DataContext = ViewModel;

        }
 

Но это не работает, и отладчик не выдает ошибку. Как я могу правильно связать viewmodel с xaml?

ОБНОВИТЬ мой шаблон выглядит следующим образом :

 <DataTemplate x:Key="ListViewModelTemplate"> <!-- for recent recepies-->

            <Grid Width="400" Height="80" VerticalAlignment="Center">

                <StackPanel Orientation="Vertical">
                    <Border CornerRadius="0" x:Name="brdTesat" BorderBrush="Black" BorderThickness="1" Width="80" Height="80">

                    <Border.Background>
                        <ImageBrush x:Name="backgroundImaageBrush" Stretch="Fill">

                            <ImageBrush.ImageSource>

                                    <BitmapImage x:Name="bmapBackground" UriSource="{Binding imageUriPath}" >
                                </BitmapImage>

                            </ImageBrush.ImageSource>
                        </ImageBrush>
                    </Border.Background>
                </Border>
                    <StackPanel>
                    <TextBlock TextAlignment="Left" Margin="7,4,4,4" Text="{Binding title}" TextWrapping="Wrap"></TextBlock>
                        <TextBlock TextAlignment="Left" Margin="7,4,4,4" Text="DA" TextWrapping="Wrap"></TextBlock>
                    </StackPanel>
                </StackPanel>

            </Grid>
        </DataTemplate>
 

ОБНОВЛЕНИЕ 2

я изменил свой код listbox на :

 <ListBox x:Name="recepiesList"  ItemsSource="{Binding recepiesList}" >             </ListBox>
 

Без шаблона я получаю список [project_name].Model.MainViewModelItem , поэтому я думаю, что есть проблема с шаблоном.. Что я делаю не так?

Ответ №1:

Вам нужно привязать свой список к данным. Итак, это должно сработать для вас.

 <ListBox x:Name="recepiesList" ItemsSource="{Binding recepiesList}" ItemTemplate="{StaticResource ListViewModelTemplate}"  />
 

Комментарии:

1. не работает .. я получаю: первое случайное исключение типа ‘System.IO.FileNotFoundException’ произошло в mscorlib.dll Система. Windows. Ошибка данных: ошибка пути к BindingExpression: свойство ‘title’ не найдено в ‘WP7SQLiteClient. Модель. MainViewModelItem’ ‘WP7SQLiteClient. Модель. MainViewModelItem’ (хэш-код = 65782377

2. т.е. строка субтитров не отображается, потому что я не привязываю ее, я даю ей статическую строку

3. Потому что свойства вашей viewmodel не являются общедоступными! Сделайте их общедоступными и будьте счастливы 🙂

4. ах, вы правы насчет общественности, но я все еще ничего не показываю

5. нет ошибки, но не отображаются элементы в списке .. нет ошибок в выводе

Ответ №2:

Мы используем MEF в проекте, и мы связываем модели представления со следующим кодом в View.xaml.cs:

 [Import]
public ConnectionStringSetupViewModel ViewModel
{
    get { return DataContext as ConnectionStringSetupViewModel; }
    set { DataContext = value; }
}
 

Это позволяет выполнить импорт при создании каталогов. Если вы не используете MEF, вы можете использовать тот же код, что и выше, без импорта, но при создании вашего представления вам придется назначить ему новый экземпляр вашего класса viewmodel.

Комментарии:

1. Как я могу назначить новый экземпляр моего класса viewmodel ? я не уверен, что вы имеете в виду

2. PanaromaView p = новый PanaromaView(); p.ViewModel = новый PanaromaViewModel();

3. я добавил UPDATE2, пожалуйста, посмотрите

4. Это именно то, что вы получите без назначенного шаблона. Я думаю, что как только вы объедините как ItemsSource, так и ItemsTemplate, вы будете там, где вам нужно быть.