2

I'm trying to reference a LinearGradientBrush with the XAML parser, but it can't identify the object and I get the exception:

"Cannot create unknown type 'LinearGradientBrush'"

Is it possible to make this type recognized at runtime?

Here is the code I'm using:

public static class CustomBrushes
{
    public static Brush LinGrad_Bevel()
    {
        
        
        StringReader sr = new StringReader(@"<LinearGradientBrush EndPoint='0.5,1' MappingMode='RelativeToBoundingBox' StartPoint='0.5,0'>
                <GradientStop Color='#00F7F7F7' Offset='0'/>
                <GradientStop Offset='1'/>
                <GradientStop Color='Black' Offset='0.741'/>
                <GradientStop Color='Black' Offset='0.75'/>
                <GradientStop Color='White' Offset='0.25'/>
            </LinearGradientBrush>");
        XmlReader xr = XmlReader.Create(sr);


        return (Brush)XamlReader.Load(xr);
    }
}

I really don't like programing in XAML (especially because most of what I do is design dependent on runtime program flow, but some objects are just way easier to prototype in it than C# and I'd prefer to be able to employ this method...

I've read I'm supposed to include a line like this somewhere, but honestly I don't understand why and it doesn't seem to work if I stick it under all the "usings"

[assembly: XmlnsDefinition("http://schemas.microsoft.com/netfx/2007/xaml/presentation" , "System.Windows.Media")]

Anyway, any help with runtime parsing of XAML in C# code files would be appreciated.

StayOnTarget
  • 11,743
  • 10
  • 52
  • 81
ThisHandleNotInUse
  • 1,135
  • 1
  • 10
  • 23
  • 2
    SOC (separation of concerns) exists to be done! If you realy need to do this, use the Object from the WPF API. – Fals Mar 11 '15 at 23:42
  • The entire code for this particular UserControl is done in codebehind. I'm not familiar enough with XAML as to how to procedurally do a lot of alterations to the GUI at runtime without using C# which is what this UserControl does (a lot of adding and subtracting grid objects and resizing them, etc) - but I can do it in C#. I just thought it would be easier to design a brush how I like it and parse it rather than manually writing it out in C#... – ThisHandleNotInUse Mar 11 '15 at 23:46

1 Answers1

4

To answer your specific question, the namespace declarations need to be provided when the XAML is being compiled. The easiest way to do that is to just insert them in your string. For example:

StringReader sr = new StringReader(@"
    <LinearGradientBrush
        xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
        xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
        EndPoint='0.5,1' MappingMode='RelativeToBoundingBox' StartPoint='0.5,0'>
    <GradientStop Color='#00F7F7F7' Offset='0'/>
    <GradientStop Offset='1'/>
    <GradientStop Color='Black' Offset='0.741'/>
    <GradientStop Color='Black' Offset='0.75'/>
    <GradientStop Color='White' Offset='0.25'/>
</LinearGradientBrush>");
XmlReader xr = XmlReader.Create(sr);

return (Brush)XamlReader.Load(xr);

Now, that said, I would say that the above seems to me to be the least preferable way to go about this. If you want a reusable Brush object and you want to use XAML to declare it instead of going through the actual WPF programmatic API, I think a better way to do it is to put the declaration in one of the related Resources collections in your program.

For example, if you want to be able to use it throughout your program, in a number of different windows, you might make it a global resource by putting it into your App.xaml file:

<Application x:Class="TestSO28999367XamlReader.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="MainWindow.xaml">
  <Application.Resources>
    <LinearGradientBrush x:Key="beveledLinearGradientBrush"
                    EndPoint='0.5,1' MappingMode='RelativeToBoundingBox' StartPoint='0.5,0'>
      <GradientStop Color='#00F7F7F7' Offset='0'/>
      <GradientStop Offset='1'/>
      <GradientStop Color='Black' Offset='0.741'/>
      <GradientStop Color='Black' Offset='0.75'/>
      <GradientStop Color='White' Offset='0.25'/>
    </LinearGradientBrush>
  </Application.Resources>
</Application>

If your use would be limited to just one Window object or even some sub-element of that, you can add the declaration in the Resources collection for that object instead of putting it in App.xaml.

Regardless, then you can access it with this expression:

(Brush)FindResource("beveledLinearGradientBrush")

Of course, you can make the key for the resource anything you want…it doesn't have to be beveledLinearGradientBrush.

You can still use that to initialize some code-behind resource, by using the above C# expression to retrieve the object. However, note that when you do it the above way, the brush also becomes available for direct use in any XAML, via the expression "{StaticResource beveledLinearGradientBrush}".

For example:

<Border Background="{StaticResource beveledLinearGradientBrush}"/>
Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
  • That's great, I confess I had kind of thought maybe I could just declare the objects in a resource dictionary and still access them in C# after I made this post - but I wasn't really thinking about it like that prior. The problem is my user control object is going to be in a DLL so I'd like to not have to make any adjustments to the application to use the user control and I'm still struggling with trying to figure out exactly how XAML can be included in DLL's – ThisHandleNotInUse Mar 12 '15 at 22:34
  • I'm brand new to WPF - sorry I sound so lost on this - it's outside my normal method of thinking regarding writing C# – ThisHandleNotInUse Mar 12 '15 at 22:35
  • @ThisHandleNotInUse: XAML resources work fine in DLLs. Have you had some specific difficulty using them there? – Peter Duniho Mar 13 '15 at 00:57
  • I started on WPF a week ago - I just haven't dedicated enough research yet on how to do it precisely. If my user control is written completely in C# (the one I'm working on is - not an ounce of XAML) is there a way to add a resource library to it that will only be loaded if the Control is created? – ThisHandleNotInUse Mar 13 '15 at 01:02
  • I think what it was was that I couldn't figure out how to get the path to correctly reference the XAML file in the DLL from the application. I just don't understand the nature of pathing to resources in a DLL – ThisHandleNotInUse Mar 13 '15 at 01:17
  • @ThisHandleNotInUse: "completely in C#...is there a way to add a resource library to it that will only be loaded if the Control is created" -- I don't know. Probably, but I doubt it's practical to try to. If you declare the control in XAML, and put your resources in the control, those resources should also only be loaded if the control is created. – Peter Duniho Mar 13 '15 at 01:26
  • @ThisHandleNotInUse: "how to get the path to correctly reference the XAML file in the DLL from the application" -- it depends on what you mean about "resource". AFAIK, a "resource" declared in XAML is not really the same as a normal resource one might put in a DLL. That is, while the XAML data may be stored itself as a resource, when you declare something in XAML as a member of a "Resources" collection, I don't know whether that actually shows up as an actual _resource_ per se in the assembly. – Peter Duniho Mar 13 '15 at 01:28
  • I can't for the life of me figure out how to path to a XAML file in a DLL which is why I just gave up. Everything I try throws a parse exception and it doesn't help that the IDE gives you no suggestions on paths or anything when writing in XAML. – ThisHandleNotInUse Mar 13 '15 at 01:28
  • @ThisHandleNotInUse: FWIW, I'm relatively new to WPF myself. I have dipped my toe in now and then over the years, but only since the last six months have made a real effort to understand it. One thing I have learned: your life will be much easier in the long run if you embrace the concept of XAML and data binding, two technologies that form the foundation of WPF. WPF was designed to work that way, and attempting to use it without those elements, you'll be fighting with WPF the whole way. – Peter Duniho Mar 13 '15 at 01:30
  • I just don't understand what: "pack://application:,,,//ResourceAssembly;blah blah blah" means nor can I find what it's talking about in the object browser of the DLL - in short - I have absolutely no clue what I'm doing and am only trying to work in WPF because I need its rendering capacity for the project I'm working on. – ThisHandleNotInUse Mar 13 '15 at 01:31
  • @ThisHandleNotInUse: "I can't for the life of me figure out how to path to a XAML file in a DLL" -- well, you seem to be comfortable posting your questions about how to work _around_ XAML. You might consider posting questions about how to work _with_ XAML. :) – Peter Duniho Mar 13 '15 at 01:31
  • Sigh... but XAML is the devil - it taught me that after I spent five hours trying to reference a resource dictionary in a DLL with no success. Who the hell puts three commas in a path syntax? Why are they even there? ---- kidding - I'll look into it more. – ThisHandleNotInUse Mar 13 '15 at 01:39