2016-01-24 3 views
3

Как привязать данные к значению случая объединения в XAML?Как привязать данные к значению случая объединения в XAML?

В настоящее время привязанное к данным значение указывает на объект String20 вместо фактического строкового значения, которое обертывает случай объединения (т. Е. String20).

Пример:

<ListView ItemsSource="{Binding Modules}" DisplayMemberPath="Author.First" /> 

Автор Определение:

type Name = { 
    First:String20 
    Last:String20 
    Suffix:String20 option 
} 

type Module = { 
    Author:Name 
    Duration:Duration 
} 

XAML:

<Window x:Class="Client.MainWindow" 
     ... 
     xmlns:manageModules="clr-namespace:ManageModules;assembly=ManageModules"> 

    <Window.DataContext> 
     <manageModules:CreationViewModel /> 
    </Window.DataContext> 

    <Grid> 
     <ListView ItemsSource="{Binding Modules}" DisplayMemberPath="Author.First" 
        TextElement.Foreground="LightBlue" Background="Black" /> 
    </Grid> 
</Window> 

ViewModel:

namespace ManageModules 
    ... 
    type CreationViewModel() = 
     inherit ViewModelBase() 
     let name =  { First=String20("Scott"); Last=String20("Nimrod"); Suffix=None } 
     let duration = { Hours=1; Minutes=30; Seconds=0 } 
     let moduleItem = { Author=name; Duration=duration } 

     let mutable (_modules:Module ObservableCollection) = ObservableCollection() 

     do _modules.Add(moduleItem) 

     member this.Modules 
      with get()  = _modules 
      and set(value) = _modules <- value 

     member this.Add moduleItem = 
      _modules.Add(moduleItem) 

Бизнес Доменные:

module ManageModule.Entities 

type Duration = { 
    Hours:int 
    Minutes:int 
    Seconds:int 
} 

type String20 = String20 of string 

type Name = { 
    First:String20 
    Last:String20 
    Suffix:String20 option 
} 

type Module = { 
    Author:Name 
    Duration:Duration 
} 

and Section = 
    | Introduction of Module 
    | Conclusion of Module 
    | Content of Module list 

ответ

6

Моя рекомендация будет модифицировать String20 так, что она включает в себя дополнительный элемент, который является простым string значение - и тогда вы можете связать с обычный участник string.

Для добавления элемента к типу, вы можете написать:

type String20 = 
    | String20 of string 
    member this.Value = 
    let (String20(str)) = this 
    str 

Тогда вы должны быть в состоянии написать:

<ListView ItemsSource="{Binding Modules}" DisplayMemberPath="Author.First.Value" /> 

Есть, вероятно, более сложные способы решения этого - я думаю, WPF имеет некоторый механизм для указания преобразований, которые происходят в привязках за кулисами, но добавление Value в качестве члена, вероятно, является хорошим простым началом.

0

Другой подход - использовать ValueConverter, о котором говорил Томас.

Этот пример написан на C#. Позже, когда я нахожу больше времени, я продемонстрирую тот же подход, используя F #.

Я предпочитаю сохранять простоту в логике домена и НЕ позволять интерфейсам пользовательского интерфейса или хранилища данных диктовать (то есть брать заложники) логику домена.

В результате, я предоставил следующий преобразователь значений с помощью C#:

using System; 
using System.Globalization; 
using System.Windows.Data; 
using static ManageModule.Entities; 

namespace Client.Converters 
{ 
    public class String20Converter : IValueConverter 
    { 
     public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
     { 
      var unionCase = value as String20; 
      return unionCase.Item; 
     } 

     public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
     { 
      throw new NotImplementedException(); 
     } 
    } 
} 

Обновленный XAML выглядит следующим образом:

<Window x:Class="Client.MainWindow" 
     ... 
     xmlns:local="clr-namespace:Client" 
     xmlns:manageModules="clr-namespace:ManageModules;assembly=ManageModules" 
     xmlns:converters="clr-namespace:Client.Converters" 
     mc:Ignorable="d" 
     Background="Black" 
     Title="MainWindow" Height="350" Width="525"> 

    <Window.DataContext> 
     <manageModules:CreationViewModel /> 
    </Window.DataContext> 

    <Window.Resources> 
     <converters:String20Converter x:Key="String20Converter" /> 
    </Window.Resources> 

    <Grid> 
     <ListView ItemsSource="{Binding Modules}" Background="Black"> 
      <ListView.ItemTemplate> 
       <DataTemplate> 
        <TextBlock Text="{Binding Author.First, Converter={StaticResource String20Converter}}" 
           Foreground="LightBlue" /> 
       </DataTemplate> 
      </ListView.ItemTemplate> 
     </ListView> 
    </Grid> 
</Window> 

Обратите внимание, как мы можем сохранить наши исходная логика домена:

type Duration = { 
    Hours:int 
    Minutes:int 
    Seconds:int 
} 

type String20 = String20 of string 

type Name = { 
    First:String20 
    Last:String20 
    Suffix:String2 
} 
Смежные вопросы