I have many very similar resources in xaml (varying by a tiny bit: name of property in bingings, static text in header, etc.) which are quite big and complex:
<Window.Resource>
<A x:Key="a1"> ... </A>
<A x:Key="a2"> ... </A>
...
<B x:Key="b1"> ... />
<B x:Key="b2"> ... />
...
<C x:Key="c1"> ... />
...
</Window.Resource>
And my aim is to have just this:
<A x:Key="a" ... />
<B x:Key="b" ... />
<C x:Key="c" ... />
...
where resource become kind of template. But then I need to somehow define a parameter to alter each such resource (e.g. to modify property name in the binding) before using it.
My current idea is to manipulate resources as text:
var xaml = @"... Text = ""{Binding %PROPERTY%}"" ...";
xaml = xaml.Replace("%PROPERTY%", realPropertyName);
view.Content = XamlReader.Parse(xaml)
But defining xaml strings in code-behind doesn't sounds good, they should be a part of xaml, where they are used.
So I had this brilliant idea:
// get some resource and restore xaml string for it, yay!
var xaml = XamlWriter.Save(FindResource("some resource"));
But unfortunately XamlWriter is very limited, it didn't worked, the restored this way xaml is totally unusable.
Then I had a thought to define resource as string:
<clr:String x:Key="a">...</clr:String>
But multiline string and special character in xaml making this approach looking very ugly. Don't try it at home.
Ideally I want to define resources as before (to have intellisence and stuff) and just want to modify them at run-time somehow, therefore my question.
The localized case of the problem (it's quite the same) is to have parameter in DataTemplate
. I was asking question about dynamic columns earlier, that's why I have so many similar resources defined currently and trying to find a solution again.
I forgot to add a concrete example of resource as well as some form of MCVE:
<Window.Resources>
<GridViewColumn x:Key="column1">
<GridViewColumn.Header>
<DataTemplate>
<TextBlock Text="Header1" />
</DataTemplate>
</GridViewColumn.Header>
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Value1}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
...
... more similar columns
...
</Window.Resources>
<ListView x:Name="listView" ItemsSource="{Binding Items}">
<ListView.View>
<GridView />
</ListView.View>
</ListView>
some columns are added
var view = (GridView)listView.View;
foreach(var column in Columns.Where(o => o.Show))
view.Columns.Add((GridViewColumn)FindResouce(column.Key));
where Columns
collection defines which columns can be shown, which are hidden, their width, etc.
public class Column
{
public string Key { get; set; } // e.g. "column1"
public bool Show { get; set; }
...
}
To have 100 columns I have to define 100 "columnX"
resources, but they are very similar. My challenge is to define just one and then somehow alter dynamic parts (in this case to change "Header1"
to "Header2"
and "Value1"
to "Value2"
).