0

using c#, WPF

I try to create IValueConverter for converting ID from dataBase to another value from another table in same dataBase. Example: I have one person with ID "1" and in another table NAME "James" for this ID. What I want - to bind ID to some control, and to convert ID in to NAME.

During creating such converter, I got some problem - I can't create converter to non static value. My Question - Are it's possible to create IValueConverter with non static value?

EDIT:

This is what was done:

public object Convert(object value,  Type targetType, 
        object parameter,  System.Globalization.CultureInfo culture)
    {
        using (var dbContext = new EducationDataBaseEntities())
        {
            //list for all existing id
            List<int> id = null;

            //add existing id to list
            foreach (var item in dbContext.GradeSet)
            {
                id.Add(item.GradeId);
            }

            //check each item and return equialent from db
            foreach (int item in id)
            {
                switch (Int32.Parse((string)parameter))
                {
                    case item:
                        {
                            foreach (var items in dbContext.GradeSet)
                            {
                                if (item == items.GradeId)
                                {
                                    return items.Equialent;
                                }
                            }
                        }
                }
            }
            return Binding.DoNothing;
        }
    }
hbk
  • 10,908
  • 11
  • 91
  • 124
  • 1
    By this, do you mean you need a bindable ConverterParameter (or something similar)? – BradleyDotNET Jul 15 '14 at 21:29
  • If be hones never hear about `bindable ConverterParameter` – hbk Jul 15 '14 at 21:30
  • 3
    This is subjective, but I think a value converter is the wrong place to do things such as opening database connections. A property on your model (or viewmodel?) would be more appropriate. – Jon Jul 15 '14 at 21:31
  • Totally agree with @Jon you should get the collection some other way (Dependency Property sounds right here). Either way, could you clarify what you mean by "create IValueConverter with non-static value"? There are lots of ways to get dynamic (updating) data into a converter, but I don't want to recommend one until I understand what you are trying to accomplish. – BradleyDotNET Jul 15 '14 at 21:35
  • @BradleyDotNET I just try to show all fields from some table in db, and one of this table it's ID from another table. So mean i have next example - PERSON - John, Speciality - 5, and 5 - it's ID from another table, if i look to DESCRIPTION of speciality with ID 5 i found Teacher. What i wnat - to show Teacher instead of 5. For this purpose i try to use IValueConverter. – hbk Jul 15 '14 at 21:39
  • Alright, now I understand what you want. Thanks for the information! – BradleyDotNET Jul 15 '14 at 21:42
  • @BradleyDotNET i have a grid, and for grid I already make binding to one table, and currently i try to find solution for changing just one column in grid, read a little bit about IValueCOnverter, think that i can help, if no, maybe you can help and show me another, better solution – hbk Jul 15 '14 at 21:42
  • @BradleyDotNET that's not subjective. Opening a database connection inside an `IValueConverter` is sinful and filthy and punished with eternal torture and pain in the nonconsuming flames of hell. – Federico Berasategui Jul 15 '14 at 21:48
  • @Kirill delete all your code and create a proper ViewModel and all your problems will magically disappear. This sounds like your ViewModel is not suitable for the View's needs or there isn't an actual ViewModel and you're binding UI to Data directly, which introduces the need for `IValueConverter` and all sorts of undesired stuff. Create a proper ViewModel and all your problems will magically disappear. – Federico Berasategui Jul 15 '14 at 21:50
  • @HighCore thanks for advice, for making proper ViewModel I must to learn and find "proper way" - I doing it now, hope this mistake in my code making me closer to this – hbk Jul 15 '14 at 21:55
  • @Kirill a "proper ViewModel" is any class that implements `INotifyPropertyChanged` and "matches" as much as possible the data you must show in the View. If the data from the database somehow does not "fit" into the View, the ViewModel is the one who will "transform" or "convert" the data in a suitable format for display. That pretty much removes the need for `IValueConverter`s. – Federico Berasategui Jul 15 '14 at 21:57
  • @HighCore While I agree in general, there are (many) valid uses for `IValueConverter` and `IMultiValueConverter`. Trying to avoid it to start with *is* a good strategy, but the OP shouldn't be afraid to use them when he knows when they are a good idea. – BradleyDotNET Jul 15 '14 at 22:00
  • @HighCore - I got my problem - currently i use ZERO property that implement `INotifyPropertyChanged`. I read about, try to implement in my code – hbk Jul 15 '14 at 22:00

1 Answers1

3

It looks like you are using Entity Framework, so the simple solution is to let the (presumably existing) navigation property do its job:

<TextBlock Text="{Binding Description.Name}"/>

This assumes the text "Teacher" is in the "Name" column in the "Description" table. You mentioned needing to edit it, which can get really complicated when dealing with the database itself (creating new records, etc.) A properly set up ComboBox control could do this for you (bind SelectedValue instead of Text).

If you dont have EF, or can't use navigation properties for some reason, do the following:

  1. Have your converter derive from DependencyObject
  2. Create a DependencyProperty that is a collection of Description objects (call it ItemsSource)
  3. Bind to the Descriptions collection in your view model (this assumes window has its name set to "root"):

    <local:MyConverter ItemsSource="{Binding Source={x:Reference Name=root}, Path=DataContext.Descriptions}"/>
    
  4. Utilize the collection:

    public object Convert(object value, ...)
    {
       if (value is Person)
       {
           Person dude = (Person)value;
           return ItemsSource.FirstOrDefault(d => d.Id == dude.DescriptionId);
       }
    }
    

Convert back is somewhat similar for editing purposes.

Definitely go with the first option if you can, but knowing the second can be really useful!

BradleyDotNET
  • 60,462
  • 10
  • 96
  • 117
  • Yes, I use EntityFramework, and I forget about navigation property at all - try as you sad - in my case `Binding="{Binding TeacherSet.Name}"` - result - I got exactly what i need. Thanks for explanation and help – hbk Jul 15 '14 at 22:04