#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, вы будете там, где вам нужно быть.