views:

1692

answers:

1

Perhaps it would be better if I explained why I need to do this.

This is not the true example, but in my working solution, the user will start with a relation group like this:

Apple -> Red Banana -> Yellow

In the app, in different screens (e.g. Add fruit and add color) they have the power to add new fruits/colors. They then need to link these in this screen I am building here, but also need to be able to change the relationship. So as such, I cannot define the list hardcoded in xaml, as the user can change it. So I need to load this list and then display it in the Comboboxes. So far none of the solutions below have worked to achieve this.

Have a question regarding StaticResource in the context below:

<toolkit:DataGridTextColumn Header="Name"
         Binding="{Binding Name}"
         Width="5*" />

<toolkit:DataGridComboBoxColumn Header="Color"
         ItemsSource="{Binding Source={StaticResource AllColors}}"
         SelectedValueBinding="{Binding Path=Color}"
         TextBinding="{Binding Path=Color}"
         Width="5*" />

Where AllColors would be defined as:

<x:Array x:Key="AllColors"
         Type="sys:String">
    <sys:String>Orange</sys:String>
    <sys:String>Yellow</sys:String>
</x:Array>

Except what I really want to do is set that StaticResource programmatically, to a list or array of strings.

So how could I do that?

Thanks.

Edit 1

Here's what I tried:

        // find resource object

        //var resource = (string[])Resources["Colors"];
        var i = 0;
        var colors = new string[] { };

        foreach (var fruit in fruitList)
                        {
                            colors[i] = fruit.Color;
                            i++;
                        }

        Resources["Colors"] = colors;

Doesn't work.

Please help.

Edit 2: my complete code - should make it more obvious how I am strugglign with defining the resource programatically

<UserControl x:Class="Wpf.Screen"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:toolkit="http://schemas.microsoft.com/wpf/2008/toolkit" xmlns:Wpf="clr-namespace:Wpf" MinHeight="300" MinWidth="300" Loaded="Screen_Loaded"
    Name="Fruits">

<GroupBox>
            <toolkit:DataGrid Name="dgFruits" 
            AutoGenerateColumns="False"
            Margin="10"
            ItemsSource="{Binding}">

                <toolkit:DataGrid.Columns>

                    <toolkit:DataGridTextColumn
                        Binding="{Binding Name}"
                        Header="Fruit Name"
                        Width="5*"/>

                    <toolkit:DataGridComboBoxColumn Header="Color"
                                         ItemsSource="{Binding Source={StaticResource AllColors1}}"
                                        SelectedValueBinding="{Binding Path=Color}"
                                        TextBinding="{Binding Path=Color}"
                                        Width="5*" />

                </toolkit:DataGrid.Columns>
            </toolkit:DataGrid>

        </GroupBox>

C#:

namespace Wpf
{
    public partial class Screen

public ObservableCollection<Fruit> FruitCollection { get { return fruitCollection; } }

    public Screen()
        {
            LoadFruitFile(); //this loads fruit into ObservableCollection<Fruit> fruitCollection             
            InitializeComponent();
        }

private void Screen_Loaded(object sender, System.Windows.RoutedEventArgs e)
        {

            var i = 0;
            var colors = new string[] { };

            foreach (var fruit in fruitList)
            {
                colors[i] = fruit.Color;
                i++;
            }

            // define resource in the code
            Resources["AllColors1"] = colors;
            // show new values
            var resource = (string[])Resources["AllColors1"];
            if (resource != null)
                foreach (var item in resource)
                    Console.WriteLine(item);


            dgFruits.ItemsSource = FruitCollection;


}
+3  A: 

you can get resources object from your code using FindResource method or Resources property of the FrameworkElement. Check if code below would work for you:

// find resource object
//string[] resource = (string[])FindResource("AllColors");
string[] resource = (string[])Resources["AllColors"];
if (resource != null)
{
    // old values
    foreach (var item in resource)
        Console.WriteLine(item);
    // set new values
    Resources["AllColors"] = new string[] { "red", "blue", "green"};
}
// find resource and show its new values
resource = (string[])Resources["AllColors"];
if (resource != null)
    foreach (var item in resource)
        Console.WriteLine(item);

though I don't think it's going to work the way you want it or it's a correct solution for your task. What you can do is define a class with colors collection:

public class TestColors
{
    public TestColors()
    {
        Colors = new ObservableCollection<string>();
        Colors.Add("red");
        Colors.Add("blue");
        Colors.Add("green");
    }

    public ObservableCollection<string> Colors { get; set; }
}

in your xaml you can define an ObjectDataProvider of the given object type and bind your control to its Colors property. Smth like this:

...
xmlns:local="clr-namespace:YourNamespace"
...
<Window.Resources>
     <ObjectDataProvider x:Key="AllColors0" ObjectType="{x:Type local:TestColors}"/>
</Window.Resources>
...
<ListBox ... 
     DataContext="{StaticResource AllColors0}"
     ItemsSource="{Binding Colors}"/>
...

another way of how you can do it is binding your controls to a property of the window, smth like this:

public partial class MainWindow : Window
{
    public static string[] TestProperty
    {
        get
        {
            List<string> result = new List<string>();
            result.Add("red");
            result.Add("green");
            result.Add("blue");
            return result.ToArray();
        }
    }

    public MainWindow()
    {
        InitializeComponent();
     ...

xaml:

<ListBox ...
         ItemsSource="{x:Static local:MainWindow.TestProperty}"/>

update0: define resource in the code

// define resource in the code
Resources["AllColors1"] = new string[] { "red1", "blue1", "green1" };
// show new values
resource = (string[])Resources["AllColors1"];
if (resource != null)
    foreach (var item in resource)
        Console.WriteLine(item);

hope this helps, regards

serge_gubenko
Tried your first and last suggestion so far.First didn't work it couldn't find the AllColors.Cannot find resource named '{AllColors}'. Resource names are case sensitive. Error at object 'System.Windows.Data.Binding' in markup file 'Wpf;component/screen.xaml' Line 48 Position 41.Second didn't work I get this error:Exception has been thrown by the target of an invocation. Error at object 'Microsoft.Windows.Controls.DataGridComboBoxColumn' in markup file 'Wpf;component/screen.xaml' Line 48 Position 41.
baron
where AllColors is declared? Try moving it to Window.Resources section of your xaml. I've actually tested code provided and it worked for me. But as I suggested before; that's not the way of doing this; see if suggestion #2 or #3 would work for you
serge_gubenko
I thought I was defining it there in the code...
baron
see code in update0 for my original answer would help; you need to define resources before accessing them
serge_gubenko
far out, number #2 won't work either because this is inside a usercontrol not a window...
baron
It still cannot be find the resource with the updated codeCan you show me what xaml you need for that to work in your example
baron
@baron, option #2 in @serge's post should work fine. As for it being in a user control, it shouldn't matter, user controls have local resources too: *<UserControl.Resources></UserControl.Resources>*.
slugster