0

我正在尝试从 Winform 切换到 WPF,到目前为止这很痛苦。

无论如何,我试图让这个绑定的东西使用 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 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 绑定是可编辑的。所以该字段不会是只读的。我听说我可能需要设置双向绑定,但我不知道该怎么做。

任何帮助表示赞赏。谢谢!

4

3 回答 3

2

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

No, it's not. WPF is the best UI Framework in the history of mankind. winforms (or anything else) can't even be compared with it.

Your problem is you're trying to use a winforms approach in WPF and you fail. WPF does not support developers with a winforms mentality.

All the horrible code behind hacks you're used to from winforms are completely unneeded in WPF.

Please read Rachel's Excellent Answer (and linked blog posts) about the mindshift needed when upgrading from winforms to WPF.


As mentioned in @JasRaj's answer, you're missing a DisplayMemberBinding in this case. I tested your code and added that, like this:

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

And it worked perfectly.


After a second read to your question I realized you wanted to make one of these columns editable.

First of all I will say that while what you want can be achieved with a ListView, using a DataGrid is easier.

You need to remove the DisplayMemberBindings from the ListView in order to use a CellTemplate, and therefore you need to modify the template slightly:

    <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>

I have placed a ListView and a DataGrid side by side so you can compare them:

enter image description here

Here is the 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>
  • Notice how the ListView requires DataTemplates in order to support edition, and is read-only by default, while the DataGrid is editable by default, does not need any special templats and requires that you add the IsReadOnly="True" to columns that are intended to be read-only.

  • Also, I noticed you're adding items manually to the ListView using procedural code. This is not desired in WPF. You must use an ObservableCollection<> and manipulate that collection, and let the WPF Binding engine update the UI for you.

  • It is recommended and desired that you Separate logic/data from UI in WPF.

  • If you need further clarification please let me know.

  • WPF Rocks.
于 2013-09-07T12:33:35.807 回答
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>
于 2013-09-07T13:47:36.213 回答
1

将 Gridview 的第二列与 OriginalMessage 属性绑定。

喜欢 :-

DisplayMemberBinding="{绑定路径=OriginalMessage}"

它应该工作。

于 2013-09-07T07:30:20.800 回答