开发者

Problem with Data Binding ViewModel

开发者 https://www.devze.com 2023-01-17 19:54 出处:网络
I have a ViewModel class FontsViewModel : ObservableObject { public FontsViewModel() { InitFonts(); } public ObservableCollection<Typeface> Fonts

I have a ViewModel

class FontsViewModel : ObservableObject
{
    public FontsViewModel()
    {
        InitFonts();
    }

    public ObservableCollection<Typeface> Fonts
    {
        get;
        private set;
    }

    protected void InitFonts()
    {
        Fonts = (ObservableCollection<Typeface>)System.Windows.Media.Fonts.SystemFontFamilies;
    }
}

and i bind it in XAML

<ribbon:RibbonComboBox.DataContext>
    <vm:FontsViewModel />
</ribbon:RibbonComboBox.DataContext>
<ribbon:RibbonGallery>
    <ribbon:RibbonGalleryCategory ItemsSource="{Binding Fonts}">
        <ribbon:RibbonGalleryCategory.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding}" FontFamily="{Binding}" />
            </DataTemplate>
        </ribbon:RibbonGalleryCategory.ItemTemplate>
    </ribbon:RibbonGalleryCategory>
</ribbon:RibbonGallery>

when i try running, i get

System.Windows.Markup.XamlParseException occurred
  Message='The invocation of the constructor on type 'MarkdownEditMVVM.ViewModels.FontsViewModel' that matches the specified binding constraints threw an exception.' Line number '57' and line position '26'.
  Source=PresentationFramework
  LineNumber=57
  LinePosition=26
  StackTrace:
       at System.Windows.Markup.XamlReader.RewrapException(Exception e, IXamlLineInfo lineInfo, Uri baseUri)
       at System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings settings, Uri baseUri)
       at System.Windows.Markup.WpfXamlLoader.LoadBaml(XamlReader xamlReader, Boolean skipJournaledProperties, Object rootObject, XamlAccessLevel accessLevel, Uri baseUri)
       at System.Windows.Markup.XamlReader.LoadBaml(Stream stream, ParserContext parserContext, Object parent, Boolean closeStream)
       at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator)
       at MarkdownEditMVVM.MainWindow.InitializeComponent() in d:\Projects\MarkdownEdit\MarkdownEditMVVM\MainWindow.xaml:line 1
       at MarkdownEditMVVM.MainWindow..ctor() in D:\Projects\MarkdownEdit\MarkdownEditMVVM\MainWindow.xaml.cs:line 25
  InnerException: System.InvalidCastException
       Message=Unable to cast object of type 'System.Collections.ObjectModel.ReadOnlyCollection`1[System.Windows.Media.FontFamily]' to type 'System.Collections.ObjectModel.ObservableCollection`1[System.Windows.Media.Typeface]'.
       Source=MarkdownEditMVVM
       StackTrace:
            at MarkdownEditMVVM.ViewModels.FontsViewModel.InitFonts() in D:\Projects\MarkdownEdit\MarkdownEditMVVM\ViewModels\FontsViewModel.cs:line 26
            at MarkdownEditMVVM.ViewModels.FontsViewModel..ctor() in D:\Projects\MarkdownEdit\MarkdownEditMVVM\ViewModels\FontsViewModel.cs:line 15
       InnerException: 

what am i doing wrong? its like a modified version of what i see on L开发者_Python百科esters Tutorial on WPF Ribbon


You cannot convert a SystemFontFamilies to an ObservableCollection. Instead instantiate a new collection:

  Fonts = new ObservableCollection<Typeface> (Fonts.SystemFontFamilies);

edit: The above code has a mismatch between the property type and the collection type.
Instead use one of the below:

        var myFonts = new ObservableCollection<FontFamily>(Fonts.SystemFontFamilies);

        var typefaces = new ObservableCollection<Typeface>(Fonts.SystemTypefaces);


Two points:

  1. You really don't need an ObservableCollection here (if the list of Fonts will never change.) It's sufficient to expose an IEnumerable<Typeface> property.

  2. You really shouldn't be referencing a View-specific object like a Typeface from a ViewModel. It would be better to expose the available font names as strings and inject the available names through some service interface. The service interface (on the View side) would then call System.Windows.Media.Fonts.SystemFontFamilies and cast to string names. This gives you isolation for testability (your unit tests can supply their own font names.)

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号