Costin
Costin

Reputation: 773

WPF Databinding problem

I'm new to WPF and I have some difficulties when I'm trying to populate a ListView with a list of custom objects.

internal class ApplicationCode
{
    public int Code { get; set; }

    public IEnumerable<string> InstrumentCodes { get; set; }
}

I have a list of ApplicationCode which I set to ItemsSource to a ListView. I need to display the ApplicationCode.Code as a string and for the rest of the columns a check box which can be checked/unchecked depending if the column name is contained in the InstrumentCodes collection.

In order to set the check box I use a converter on databinding:

<DataTemplate x:Key="InstrumentCodeTemplate">
  <CheckBox IsEnabled="False" IsChecked="{Binding Mode=OneTime, Converter={StaticResource InstrumentSelectionConverter}}" />
</DataTemplate>

The problem I have is because I can't know which is the current column at the time of cell data binding and I can't set the ConverterParameter.

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
  ApplicationCode appCode = value as ApplicationCode;

  return appCode != null && appCode.InstrumentCodes.Contains(parameter.ToString());
}

Small example:

    Id  | Code1 | Code3 | Code4
--------------------------------
    123 |  True | False | True

Data for row 1: ApplicationCode.InstrumentCodes {Code1, Code4}

There is a way to find out the column index or name? Or there is another way to solve this problem?

Upvotes: 2

Views: 322

Answers (2)

Costin
Costin

Reputation: 773

The solution I got so far is to add the columns dynamically and to set the ConverterParameter on every column.

foreach (var instrument in instruments)
{
    var column = new GridViewColumn
                        {
                            HeaderTemplate = GetColumnHeaderTemplate(instrument),
                            CellTemplate = GetColumnCellTemplate(instrument),
                            Header = instrument,
                        };

    view.Columns.Add(column);
}

private static DataTemplate GetColumnCellTemplate(string instrument)
{
    var binding = new Binding
    {
        ConverterParameter = instrument,
        Converter = new InstrumentSelectionConverter(),
        Mode = BindingMode.OneWay
    };

    var template = new DataTemplate();
    template.VisualTree = new FrameworkElementFactory(typeof(CheckBox));
    template.VisualTree.SetBinding(ToggleButton.IsCheckedProperty, binding);

    return template;
}

I know this isn't the best solution and I would really appreciate if someone could show me a way to do this directly from .xaml.

Upvotes: 0

Aaron McIver
Aaron McIver

Reputation: 24713

The column name should be nothing more then a visual; which means the needed data should all be residing in the underlying object model. Therefore each row of data is an object.

Perhaps a restructure of your code would suffice which would also remove the need for the converter...keep in mind this is an example to get the idea across and would need modified for actual use.

    internal class ApplicationCode
    {
        private CodeService _codeService = new CodeService();

        public int Code { get; set; }
        public bool IsValidCode
        {
            get
            {
                return _codeService.DoesIntrumentCodeExist(Code.ToString());
            }
        }
    }

    internal class CodeService
    {
        private IEnumerable<string> _instrumentCodes;

        public CodeService()
        {
            //instantiate this in another way perhaps via DI....
            _instrumentCodes = new List<string>();
        }

        public bool DoesIntrumentCodeExist(String instrumentCode)
        {
            foreach (String code in _instrumentCodes)
            {
                if (code == instrumentCode)
                    return true;
            }

            return false;
        }
    }

Upvotes: 1

Related Questions