2013-09-07 3 views
0

Я пытаюсь переключиться на WPF из Winform, и пока это боль.Listview DataTemplate Binding возвращает ошибку

В любом случае, я пытаюсь заставить эту привязку работать, используя DataTemplate.

У меня есть класс:

public class TranslatorListItem 
{ 
    public string Item { get; set; } 
    public string OriginalMessage { get; set; } 
    public string TranslatedMessage { get; set; } 
    public string Sector { get; set; } 
} 

Элементы добавляются так:

TranslatorListItem TLI = new TranslatorListItem(); 
TranslatorLVI.Items.Add(TLI); 

Мой XAML DataTemplate:

<DataTemplate x:Key="MyDataTemplate"> 
    <Border BorderBrush="#FFA4D5E5" BorderThickness="1,1,0,0" Margin="6"> 
     <StackPanel Margin="6,2,6,2"> 
      <TextBox Text="{Binding}" TextWrapping="Wrap" BorderThickness="0" BorderBrush="#00000000" /> 
     </StackPanel> 
    </Border> 
</DataTemplate> 

Это, как я пытаюсь привязать но он возвращает эту ошибку: «Двусторонняя привязка требует Path или XPath».

<ListView Margin="23,224,27,54" Name="TranslatorLVI" ItemsSource="{Binding}" HorizontalContentAlignment="Stretch" 
       ItemContainerStyle="{StaticResource MyItemContainerStyle}"> 
     <ListView.View> 
      <GridView AllowsColumnReorder="False"> 
       <GridViewColumn Header="Item" DisplayMemberBinding="{Binding Path=Item}" CellTemplate="{StaticResource MyDataTemplate}" /> 
       <GridViewColumn Header="Original Message" Width="300" CellTemplate="{StaticResource MyDataTemplate}" /> 
       <GridViewColumn Header="Translated Message" DisplayMemberBinding="{Binding Path=TranslatedMessage}" CellTemplate="{StaticResource MyDataTemplate}" /> 
       <GridViewColumn Header="Sector" DisplayMemberBinding="{Binding Path=Sector}" /> 
      </GridView> 
     </ListView.View> 
    </ListView> 

Мне нужно, чтобы TranslatedMessage был доступен для редактирования. Таким образом, это поле не будет доступно только для чтения. Я слышал, мне может потребоваться установить двустороннюю привязку, но я не знаю, как это сделать.

Любая помощь приветствуется. Спасибо!

+0

Вы получаете свой список? – Nitin

+0

MyDataTemplate TextBox Связывание текста не содержит Path. –

ответ

2

I'm trying to switch over to WPF from Winform and so far it's a pain.

Нет, это не так. WPF является лучшим интерфейсом пользовательского интерфейса в истории человечества. winforms (или что-то еще) не могут сравниться с ним.

Ваша проблема в том, что вы пытаетесь использовать подход winforms в WPF, и вы терпите неудачу. WPF не поддерживает разработчиков с менталитетом winforms.

Весь ужасный код из-за хаков, с которыми вы привыкли, из winforms полностью не используется в WPF.

Просьба ознакомиться с Rachel's Excellent Answer (и связанными сообщениями в блоге) о том, что нужно для перехода от winforms к WPF.


Как упомянуто в @ ответ Джасрадж, вы пропали без вести в данном случае DisplayMemberBinding. Я проверил ваш код и добавил, что вот так:

<GridViewColumn Header="Original Message" 
       DisplayMemberBinding="{Binding OriginalMessage}" 
       Width="300"/> 

И он отлично работал.


После второго чтения на ваш вопрос я понял, что вы хотите сделать одну из этих столбцов доступной для редактирования.

Прежде всего скажу, что в то время как то, что вы хотите может быть достигнуто с помощью ListView, используя DataGridis easier.

Вы должны удалить DisplayMemberBinding S из ListView для того, чтобы использовать CellTemplate, и поэтому вам нужно немного изменить шаблон:

<DataTemplate x:Key="MyDataTemplate"> 
     <Border BorderBrush="#FFA4D5E5" BorderThickness="1,1,0,0" Margin="6"> 
      <TextBox Text="{Binding TranslatedMessage}" 
        TextWrapping="Wrap" 
        BorderThickness="0" 
        BorderBrush="#00000000" /> 
     </Border> 
    </DataTemplate> 

я поставил ListView и DataGrid бок о бок, так вы можете сравнить их:

enter image description here

Вот XAML:

<UniformGrid Columns="2"> 
    <ListView ItemsSource="{Binding}" HorizontalContentAlignment="Stretch"> 
     <ListView.View> 
      <GridView AllowsColumnReorder="False"> 
       <GridViewColumn Header="Item" DisplayMemberBinding="{Binding Path=Item}"/> 
       <GridViewColumn Header="Original Message" DisplayMemberBinding="{Binding OriginalMessage}" Width="300"/> 
       <GridViewColumn Header="Translated Message" CellTemplate="{StaticResource MyDataTemplate}" /> 
       <GridViewColumn Header="Sector"/> 
      </GridView> 
     </ListView.View> 
    </ListView> 

    <DataGrid ItemsSource="{Binding}" 
       AutoGenerateColumns="False"> 
     <DataGrid.Columns> 
      <DataGridTextColumn Header="Item" Binding="{Binding Path=Item}" IsReadOnly="True"/> 
      <DataGridTextColumn Header="Original Message" Binding="{Binding OriginalMessage}" IsReadOnly="True" Width="300"/> 
      <DataGridTextColumn Header="Translated Message" Binding="{Binding TranslatedMessage}" /> 
      <DataGridTextColumn Header="Sector" Binding="{Binding Sector}"/> 
     </DataGrid.Columns> 
    </DataGrid> 

</UniformGrid> 
  • Обратите внимание, как ListView требует DataTemplates для того, чтобы поддержать издание, и только для чтения по умолчанию, в то время как DataGrid редактируется по умолчанию, не требует каких-либо специальных templats и требует, чтобы вы добавить IsReadOnly="True" к столбцам, которые предназначены для чтения только для чтения.

  • Кроме того, я заметил, что вы добавляете элементы вручную в ListView с использованием процедурного кода. Это нежелательно в WPF. Вы должны использовать ObservableCollection<> и управлять этой коллекцией, и пусть механизм привязки WPF обновит пользовательский интерфейс.

  • Рекомендуется, чтобы вы использовали Separate logic/data from UI в WPF.

  • Если вам нужно уточнить это, пожалуйста, дайте мне знать.

  • WPF Rocks.
+0

Здравствуйте, спасибо вам за большую помощь и блоги о WPF. Я обязательно прочитаю их в ближайшее время. Я хотел бы использовать шаблон ячейки как для OriginalMessage, так и для TranslatedMessage. Однако, когда я связываю их следующим образом: Значение недействительно, потому что оно добавляет Translated to Original и отображает оба. Как я могу исправить эту проблему? Спасибо! – JonJon2244

+0

@ JonJon2244 вам нужно 2 отдельных 'DataTemplate'. Один для каждого столбца. –

+0

Да, я так делаю сейчас, но я думал, что будет более чистый способ: / – JonJon2244

1

Связать со вторым столбцом Gridview с свойством OriginalMessage.

как: -

DisplayMemberBinding = "{Binding Path = OriginalMessage}"

он должен работать.

1

По-моему, вы полностью не используете данные. вы просто используете его для отображения одного свойства; Фактически вы можете использовать DataTemplate для отображения всех данных в своем классе (TranslatorListItem); таких как

 <DataTemplate x:Key="MyDataTemplate"> 
      <Border BorderBrush="#FFA4D5E5" BorderThickness="1,1,0,0" Margin="6"> 
       <TextBox Text="{Binding Item}" 
         TextWrapping="Wrap" 
         BorderThickness="0" 
         BorderBrush="#00000000" /> 
       <TextBox Text="{Binding TranslatedMessage}" 
          TextWrapping="Wrap" 
          BorderThickness="0" 
          BorderBrush="#00000000" /> 
        ( ..... follow up) 
        </Border> 
    </DataTemplate> 
So your ListView can design like this: 
<ListView ItemsSource="{Binding}" HorizontalContentAlignment="Stretch" 
    ItemTemplate="{StaticResource MyDataTemplate}"> 
    </ListView> 
Смежные вопросы