2015-01-25 6 views
-1

У меня есть поле перечисления, которое хранится как целое в базе данных. например 1 означает собаку, 2 означает cat.Как изменить способ отображения поля в WPF?

Я хочу показать реальное имя вместо целого числа, когда я показываю данные, что лучше всего делать в WPF?

Я попытался изменить значение в DataSet, как это row["TYPE"] = Name[row["TYPE"]];, но он не работает (несовпадающий тип данных).

Данные получены с помощью этого ComboBox, а тип данных - int.

<ComboBox Height="23" Name="typeSelectComboBox" Width="190"> 
      <ComboBoxItem Tag="0" Content="Select" /> 
      <ComboBoxItem Tag="1" Content="Foo" /> 
      <ComboBoxItem Tag="2" Content="Bar" /> 
      <ComboBoxItem Tag="3" Content="Cat" /> 
      <ComboBoxItem Tag="4" Content="Dog" /> 
</ComboBox> 

Вот как я показываю данные.

 string sqlStr = "select * from AREA"; 
     OracleDataAdapter dataAdapter = new OracleDataAdapter(sqlStr, db.Connection); 
     DataSet systemDataSet = new DataSet(); 
     dataAdapter.Fill(systemDataSet); 

     if (systemDataSet.Tables[0].Rows.Count > 0) 
     { 
      /* this doesn't work. 
      foreach (DataRow row in systemDataSet.Tables[0].Rows) 
      { 
       // row["TYPE"] = Name[row["TYPE"]]; 
      } */ 
      areaListGrid.ItemsSource = systemDataSet.Tables[0].DefaultView; 
     } 

areaListGrid только основные ListGrid, которые держат данные, никакой специальной конфигурации.

<DataGrid AutoGenerateColumns="False" 
     IsReadOnly="True" 
     Grid.Row="1" Height="484" HorizontalAlignment="Left" Margin="3,4,0,0" Name="areaListGrid" VerticalAlignment="Top" Width="668"> 
<DataGrid.Columns> 
    <DataGridTextColumn Binding="{Binding ID}" Header="ID" MaxWidth="30" FontSize="12" /> 
    <DataGridTextColumn Binding="{Binding Path=NAME}" MinWidth="50" Header="Name" FontSize="12" /> 
    <DataGridTextColumn Binding="{Binding Path=TYPE}" MinWidth="10" Header="Type" FontSize="12" /> 
    <DataGridTextColumn Binding="{Binding Path=DESCRIPTION}" MinWidth="300" Header="Location" FontSize="12"> 
     <DataGridTextColumn.ElementStyle> 
      <Style TargetType="TextBlock"> 
       <Setter Property="TextWrapping" Value="Wrap"/> 
       <Setter Property="Height" Value="Auto"/> 
      </Style> 
     </DataGridTextColumn.ElementStyle> 
    </DataGridTextColumn> 
</DataGrid.Columns> 
</DataGrid> 

ответ

1

Я не знаю о простом подходе, основанном на XAML, который сопоставляет значение одного типа со значением другого типа. Однако:

  • По умолчанию привязки в WPF из enum типа в текстовый объект, как TextBlock.Text, Button.Content и т.д. будет использовать имя enum значение. В этом случае вам нечего делать. Имя значения будет отображаться как связанное значение автоматически.
  • Если по какой-либо причине вы привязываетесь не к тому, что действительно набирается как enum, но как простой int, вы должны иметь возможность реализовать IValueConverter, который выполняет сопоставление и которое вы используете в объявлении привязки экранного объекта ,

Если вы обеспечите a good, minimal, complete code example, который показывает существенную часть вашего связывания (т.е. типа enum и некоторые XAML, который показывает его), можно было бы предусмотреть более конкретный ответ.


EDIT:

К сожалению, пример кода в вопросе не является полным. Тем не менее, обращаясь к тому, что, по-видимому, представляет собой пару основных проблем & hellip;

«Я не знаю, как связать перечисление с ComboBox еще»

Это «просто работает». Например, вот простая форма XAML с TextBlock, чтобы отобразить текущее значение перечисления в MainWindow объекте, и ComboBox, где свойство Tag присваиваются само значение перечисления, как это Content свойство:

<StackPanel> 
    <TextBlock Text="{Binding ElementName=mainWindow, Path=Value}" /> 
    <ComboBox SelectionChanged="ComboBox_SelectionChanged" SelectedValuePath="Tag"> 
    <ComboBoxItem Tag="{x:Static local:Fruit.Apple}" Content="{x:Static local:Fruit.Apple}" /> 
    <ComboBoxItem Tag="{x:Static local:Fruit.Orange}" Content="{x:Static local:Fruit.Orange}" /> 
    <ComboBoxItem Tag="{x:Static local:Fruit.Banana}" Content="{x:Static local:Fruit.Banana}" /> 
    <ComboBoxItem Tag="{x:Static local:Fruit.Kiwi}" Content="{x:Static local:Fruit.Kiwi}" /> 
    </ComboBox> 
</StackPanel> 

(Предположим, объявлен enum Fruit { Apple, Orange, Banana, Kiwi }, конечно)

Примечание синтаксис для использования конкретных значений enum: {x:Static local:Fruit.Apple}.local относится к пространству имен enum, которое объявлено в атрибуте xmlns для корневого элемента XAML (например, любое пространство имен XAML), и, конечно, значение enum указано как указано в C# (то есть <enum name>.<enum value>).

TextBlock связывается непосредственно в собственности, имеющей тип Fruit.

Часть XAML составитель и WPF выполнение обрабатывать все остальное, преобразование enum значения их имена, когда они отображаются пользователю, в то время как с использованием фактических enum значения при работе со значениями в коде.

Window класс выглядит следующим образом:

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
    } 

    public Fruit Value 
    { 
     get { return (Fruit)GetValue(ValueProperty); } 
     set { SetValue(ValueProperty, value); } 
    } 
    public static DependencyProperty ValueProperty = 
     DependencyProperty.Register("Value", typeof(Fruit), typeof(MainWindow), new PropertyMetadata(Fruit.Apple)); 

    private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) 
    { 
     ComboBox comboBox = (ComboBox)sender; 

     Value = (Fruit)comboBox.SelectedValue; 
    } 
} 

Т.е. a нормальное свойство DependencyProperty и обработчик события для обновления значения свойства, когда выбран конкретный ComboBoxItem.

Непонятно из вашего примера кода, как настроен ваш DataAdapter. Но, надеюсь, он настроен на автоматическое преобразование целого числа в БД в значение типа enum в строке. Это было бы идеально, так как тогда вы можете просто привязать представление таблицы непосредственно к объекту интерфейса WPF.

Если он не настроен таким образом, я бы сосредоточил ваше внимание на этом. Но если вы действительно хотите, вы должны добавить IValueConverter в привязку, используемую для отображения строк таблицы в вашем WPF-интерфейсе. Опять же, с вопросом, не имеющим каких-либо подробностей относительно areaListGrid, я не могу сказать, как именно вы это сделаете. Но он будет работать, как и любой другой IValueConverter: просто напишите конвертер для сопоставления с int в данных БД на имя enum и используйте это в любом связывании, которое у вас есть для столбца БД для этого значения.


EDIT # 2:

Если вы на самом деле не используется enum типа, вы можете реализовать IValueConverter для обработки явного преобразования. Например:

class Int32ToValueNameConverter : IValueConverter 
{ 
    private static readonly Dictionary<int, string> _intToName = new Dictionary<int, string>() 
    { 
     { 0, "Apple" }, 
     { 1, "Orange" }, 
     { 2, "Banana" }, 
     { 3, "Kiwi" }, 
    }; 

    private static readonly Dictionary<string, int> _nameToInt = _intToName.ToDictionary(kvp => kvp.Value, kvp => kvp.Key); 

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (value is int && targetType == typeof(string)) 
     { 
      string result; 

      if (_intToName.TryGetValue((int)value, out result)) 
      { 
       return result; 
      } 
     } 

     return Binding.DoNothing; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     string text = value as string; 

     if (text != null && targetType == typeof(int)) 
     { 
      int result; 

      if (_nameToInt.TryGetValue(text, out result)) 
      { 
       return result; 
      } 
     } 

     return Binding.DoNothing; 
    } 
} 

Вы можете использовать выше в XAML как это:

<StackPanel> 
    <Button Content="Increment Int" Click="Int32Button_Click" HorizontalAlignment="Left" /> 
    <TextBlock> 
    <TextBlock.Text> 
     <Binding ElementName="mainWindow" Path="Int32Value"> 
     <Binding.Converter> 
      <local:Int32ToValueNameConverter /> 
     </Binding.Converter> 
     </Binding> 
    </TextBlock.Text> 
    </TextBlock> 
    <TextBox> 
    <TextBox.Text> 
     <Binding ElementName="mainWindow" Path="Int32Value" UpdateSourceTrigger="PropertyChanged"> 
     <Binding.Converter> 
      <local:Int32ToValueNameConverter /> 
     </Binding.Converter> 
     </Binding> 
    </TextBox.Text> 
    </TextBox> 
</StackPanel> 

При нажатии кнопки будет вращаться через целые значения, показывая результат в обоих TextBlock и TextBox. Ввод допустимого значения в TextBox приведет к обновлению связанного свойства, которое, конечно же, обновит TextBlock, чтобы отразить это изменение.

код-позади, чтобы поддержать приведенный выше пример:

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
    } 

    public int Int32Value 
    { 
     get { return (int)GetValue(Int32ValueProperty); } 
     set { SetValue(Int32ValueProperty, value); } 
    } 
    public static DependencyProperty Int32ValueProperty = 
     DependencyProperty.Register("Int32Value", typeof(int), typeof(MainWindow), new PropertyMetadata(0)); 

    private void Int32Button_Click(object sender, RoutedEventArgs e) 
    { 
     int newValue = Int32Value + 1; 

     if (newValue > 3) 
     { 
      newValue = 0; 
     } 

     Int32Value = newValue; 
    } 
} 

Я надеюсь, что вы можете применить в приведенном выше примере связывания вашего собственного DataGrid сценария и простите, что я не чувствую, что собирается усилие производства автономный пример DataGrid, который должен иметь ваш вопрос, и на котором я мог бы основывать ответ, если бы он был предоставлен.

+0

Спасибо! Я обновил код.Я использовал 'int' как тип данных, и я знаю, что это может быть не самая лучшая практика, но я не знаю, как привязать' enum' к ComboBox. – leetom

+0

@leetom: см. Мое редактирование выше –

+0

Большое спасибо за ваше терпение. Я могу сделать ошибку, упомянув перечисление. На самом деле я вообще не использовал тип «enum» (потому что сначала не думаю, что мне нужно), все, что я сделал, это попытка показать имена (строки) пользователю и сохранить данные как «целочисленные» в кода и базы данных. Это то, что я обычно делаю, когда я использую динамический типизированный язык. Но теперь в C# я не могу напрямую изменить поле 'integer' на' string'. Я пытаюсь реализовать «IValueConverter», все это новое, потому что я все еще новичок. – leetom