Program działa prawidłowo lecz w podglądzie designera (“nie zawsze”) wyrzuca wyjątek.
Jeśli wszystko umieszczam w obrębie jednego projektu problem nie występuje.
Problem również nie występuje jeśli zdefiniuje datatemplate w XAML (w przypadku również rozdzielenia np. na 2 projekty).
Wyjątek wyświetla się w podglądzie dla okna PagedCollection.ExampletView
XamlParseException: The invocation of the constructor on type 'PagedCollection.Shared.ExampleDataGridView' that matches the specified binding constraints threw an exception.
StackTrace:
at System.Windows.FrameworkTemplate.LoadTemplateXaml(XamlReader templateReader, XamlObjectWriter currentWriter)
at System.Windows.FrameworkTemplate.LoadTemplateXaml(XamlObjectWriter objectWriter)
at System.Windows.FrameworkTemplate.LoadOptimizedTemplateContent(DependencyObject container, IComponentConnector componentConnector, IStyleConnector styleConnector, List`1 affectedChildren, UncommonField`1 templatedNonFeChildrenField)
at System.Windows.FrameworkTemplate.LoadContent(DependencyObject container, List`1 affectedChildren)
at System.Windows.StyleHelper.ApplyTemplateContent(UncommonField`1 dataField, DependencyObject container, FrameworkElementFactory templateRoot, Int32 lastChildIndex, HybridDictionary childIndexFromChildID, FrameworkTemplate frameworkTemplate)
at System.Windows.FrameworkTemplate.ApplyTemplateContent(UncommonField`1 templateDataField, FrameworkElement container)
at System.Windows.FrameworkElement.ApplyTemplate()
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.ContextLayoutManager.UpdateLayout()
at System.Windows.UIElement.UpdateLayout()L
InnerException:
Exception: The component 'PagedCollection.Shared.ExampleDataGridView' does not have a resource identified by the URI '/PagedCollection;component/shared/_exampledatagridview.xaml'.
StackTrace:
at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator)
InnerException:
None
Struktura projektu:
[App.xaml]
<Application x:Class="PagedCollection.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/DataTemplates.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
[DataTemplates.xaml]
<ResourceDictionary x:Name="DataTemplates"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:shared="clr-namespace:PagedCollection.Shared"
xmlns:viewModels="clr-namespace:PagedCollectionMVVM.ViewModels;assembly=PagedCollectionMVVM">
<!--<DataTemplate DataType="{x:Type viewModels:ExampleListViewModel}">
<shared:ExampleListViewView/>
</DataTemplate>
<DataTemplate DataType="{x:Type viewModels:ExampleDataGridViewModel}">
<shared:ExampleDataGridView/>
</DataTemplate>-->
</ResourceDictionary>
[ViewModelLocator.cs]
using PagedCollection.Shared;
using PagedCollectionMVVM.Models;
using PagedCollectionMVVM.ViewModels;
using System.Windows;
using Size = PagedCollectionMVVM.Models.Size;
namespace PagedCollection
{
internal static class ViewModelLocator
{
public static ICollectionViewModel<TestModel> ExampleListViewModel
=> new CollectionViewModel<TestModel>(new ExampleListViewModel())
{
PageParameters = new PagedViewModel(1, Size._15),
EmptyCollectionVisibility = false
}.Register<ExampleListViewView>(Application.Current.Resources);
public static ICollectionViewModel<TestModel> ExampleDataGridViewModel
=> new CollectionViewModel<TestModel>(new ExampleDataGridViewModel())
{
PageParameters = new PagedViewModel(1, Size._10),
}.Register<ExampleDataGridView>(Application.Current.Resources);
}
}
[DataTemplateManager.cs]
using System;
using System.Windows;
using System.Windows.Markup;
namespace PagedCollectionMVVM.Infrastucture
{
public static class DataTemplateManager
{
public static void RegisterDataTemplate<TViewModel, TView>(ResourceDictionary resourceDictionary)
where TView : FrameworkElement
{
RegisterDataTemplate(typeof(TViewModel), typeof(TView), resourceDictionary);
}
public static void RegisterDataTemplate(Type viewModelType, Type viewType, ResourceDictionary resourceDictionary)
{
foreach (var item in resourceDictionary.Keys)
if (item is DataTemplateKey && ((DataTemplateKey)item).DataType.Equals(viewModelType)) return;
var template = CreateTemplate(viewModelType, viewType);
var key = template.DataTemplateKey;
resourceDictionary.Add(key, template);
}
private static DataTemplate CreateTemplate(Type viewModelType, Type viewType)
{
const string xamlTemplate = "<DataTemplate DataType=\"{{x:Type viewModels:{0}}}\"><view:{1} /></DataTemplate>";
string xaml = String.Format(xamlTemplate, viewModelType.Name, viewType.Name);
ParserContext context = new ParserContext
{
XamlTypeMapper = new XamlTypeMapper(new string[0])
};
context.XamlTypeMapper.AddMappingProcessingInstruction("viewModels", viewModelType.Namespace, viewModelType.Assembly.FullName);
context.XamlTypeMapper.AddMappingProcessingInstruction("view", viewType.Namespace, viewType.Assembly.FullName);
context.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
context.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");
context.XmlnsDictionary.Add("viewModels", "viewModels");
context.XmlnsDictionary.Add("view", "view");
return (DataTemplate)XamlReader.Parse(xaml, context);
}
}
}
[CollectionViewModel.cs]
using System.Linq;
using System.Collections.Generic;
using PagedCollectionMVVM.Infrastucture;
using PagedCollectionMVVM.Models;
using System.ComponentModel;
using System;
using System.Windows;
namespace PagedCollectionMVVM.ViewModels
{
public interface ICollectionView<T> where T : INotifyPropertyChanged
{
ObservableList<T> _pageElements { get; }
void Load();
}
public interface ICollectionViewModel<T> : ICollectionViewModel where T : INotifyPropertyChanged
{
ICollectionView<T> SelectedTemplate { get; }
}
public interface ICollectionViewModel
{
int Offset { get; }
void Sort(string propertyName, ListSortDirection direction);
void SetFirstPageCommand();
}
public class CollectionViewModel<TModel> : NotifyPropertyChanged, ICollectionViewModel<TModel>
where TModel : INotifyPropertyChanged
{
public ICollectionView<TModel> SelectedTemplate { get; private set; }
public PagedViewModel PageParameters
{
[...]
}
public CollectionViewModel(ICollectionView<TModel> TViewModel)
{
SelectedTemplate = TViewModel;
SelectedTemplate.Load();
_source = SelectedTemplate._pageElements.ToList();
[...]
}
public ICollectionViewModel<TModel> Register<TView>(ResourceDictionary resourceDictionary)
where TView : FrameworkElement
{
DataTemplateManager.RegisterDataTemplate(SelectedTemplate.GetType(), typeof(TView), resourceDictionary);
return this;
}
[...]
private sealed class Sorter
{
[...]
}
private sealed class Paginator
{
[...]
}
}
}
[CollectionView.xaml]
<UserControl x:Class="PagedCollection.Shared.CollectionView"
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:shared="clr-namespace:PagedCollection.Shared"
xmlns:model="clr-namespace:PagedCollectionMVVM.Models;assembly=PagedCollectionMVVM"
xmlns:converter="clr-namespace:PagedCollectionMVVM.Converters;assembly=PagedCollectionMVVM"
mc:Ignorable="d" >
<UserControl.Resources>
<converter:NullToVisibilityConverter x:Key="nullToVisibilityConverter" TrueValue="Collapsed" FalseValue="Visible" />
<BooleanToVisibilityConverter x:Key="booleanToVisibilityConverter" />
</UserControl.Resources>
<Grid>
<ContentControl Content="{Binding SelectedTemplate}" Margin="0,0,0,30"
Visibility="{Binding CollectionVisibility, Converter={StaticResource booleanToVisibilityConverter}}" />
<StackPanel Margin="0" Width="45" VerticalAlignment="Top" FlowDirection="RightToLeft" HorizontalAlignment="Right"
Visibility="{Binding PageParameters, Converter={StaticResource nullToVisibilityConverter}}">
<ComboBox ItemsSource="{Binding Source={x:Static model:Page.Size}, Mode=OneWay}" SelectedItem="{Binding PageParameters.PageSize}"/>
</StackPanel>
<shared:PagedView DataContext="{Binding PageParameters}" HorizontalAlignment="Center" VerticalAlignment="Bottom"/>
</Grid>
</UserControl>
[ExampletView.xaml]
<Window x:Class="PagedCollection.ExampletView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:shared="clr-namespace:PagedCollection.Shared"
xmlns:locator="clr-namespace:PagedCollection"
mc:Ignorable="d"
Title="ExampletView" Height="450" Width="800">
<Grid>
<TabControl>
<TabItem Header="Example1">
<TabItem.HeaderTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Example1" />
</StackPanel>
</DataTemplate>
</TabItem.HeaderTemplate>
<Grid>
<shared:CollectionView DataContext="{Binding Source={x:Static locator:ViewModelLocator.ExampleListViewModel}}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
</Grid>
</TabItem>
<TabItem Header="Example2">
<TabItem.HeaderTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Example2" />
</StackPanel>
</DataTemplate>
</TabItem.HeaderTemplate>
<Grid>
<shared:CollectionView DataContext="{Binding Source={x:Static locator:ViewModelLocator.ExampleDataGridViewModel}}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
</Grid>
</TabItem>
</TabControl>
</Grid>
</Window>