【问题标题】:WPF Textbox TwoWay binding in datatemplate not updating the source even on LostFocus数据模板中的 WPF 文本框双向绑定即使在 LostFocus 上也不会更新源
【发布时间】:2015-09-15 13:37:45
【问题描述】:

我有一个ObservableCollection<string> Tags 作为自定义对象的一部分。我将它绑定到DataTemplate,以便使用以下代码向用户显示所有标签:

<StackPanel DockPanel.Dock="Top" Margin="15,0,15,0" Orientation="Horizontal">
    <Label Content="Tags:" FontSize="14" Foreground="{StaticResource HM2LightTextBrush}"/>
    <Grid>
        <ItemsControl Name="PanelPreviewNoteTags" ItemsSource="{Binding ElementName=lbNotesQuickView, Path=SelectedItem.Tags}" Margin="3,0" Visibility="Collapsed">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <WrapPanel/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Border BorderThickness="1" BorderBrush="#676B6E" Margin="3,0">
                        <Label Content="{Binding .,Mode=OneWay}" Foreground="{StaticResource HM2LightTextBrush}"/>
                    </Border>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
        <ItemsControl Name="PanelEditNoteTags" ItemsSource="{Binding ElementName=lbNotesQuickView, Path=SelectedItem.Tags}" Margin="3,0" Visibility="Collapsed">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <WrapPanel/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Border BorderThickness="1" BorderBrush="#676B6E" Margin="3,0">
                        <StackPanel Orientation="Horizontal">
                            <TextBox Text="{Binding ., Mode=TwoWay}"/>
                            <Button Style="{StaticResource RibbonButton}" Click="ButtonRemoveTagClick" Tag="{Binding}">
                                <Image Height="16" Width="16" Source="/Poker Assistant;component/Resources/fileclose.png" />
                            </Button>
                        </StackPanel>
                    </Border>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </Grid>
</StackPanel>

ObservableCollection 中添加和删除项目按预期工作。

在代码中,我通过设置对应的PanelEditNoteTagsPanelPreviewNoteTagsVisibility 在编辑和查看模式之间切换。这一切都很好并且有效。但是当我进入编辑模式并开始为TextBox 中的标签输入新值时,源代码并没有得到更新。我当然知道当我按下Save 按钮时会引发LostFocus 事件。我尝试了所有UpdateSourceTrigger 值,还是一样。

这是否与同时绑定到相同值的两个控件有关 - 来自PanelPreviewNoteTagsLabel 和来自PanelEditNoteTagsTextBox

我在这里错过了什么?

【问题讨论】:

  • 绑定到源在没有绑定属性的情况下不起作用。由于您的绑定有Path=.,因此不会有源更新。有关更多详细信息,请参阅this answer。您必须将 ObservableCollection&lt;string&gt; 替换为具有可写字符串属性的对象集合。
  • This answer 也可能有帮助。
  • 所以我应该使用ObservableCollection&lt;Tag&gt; Tags 而不是ObservableCollection&lt;string&gt; Tags,其中Tag 类有一个string Content 属性,然后绑定到它。对吗?
  • 这正是你应该做的。

标签: wpf data-binding textbox datatemplate


【解决方案1】:

@Clemens 感谢您快速准确的回复 :) 以下是工作解决方案以供将来参考。

解决方案是不要使用ObservableCollection&lt;string&gt; Tags,因为正如 Clemens 所指出的那样,{Binding ., Mode=TwoWay} 无法返回源代码。

所以我创建了一个自定义的Tag 类:

public class Tag : INotifyPropertyChanged
{
    private string _content;
    public string Content { get { return _content; } set { _content = value; OnMyPropertyChanged(() => Content); } }

    public Tag(string content)
    { Content = content; }

    public Tag()
        : this("new tag")
    { }

    public event PropertyChangedEventHandler PropertyChanged;
    // Raise the event that a property has changed in order to update the visual elements bound to it
    internal void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }
    //CONVERTS the passed parameter to its name in string
    internal void OnMyPropertyChanged<T>(Expression<Func<T>> memberExpression)
    {
        MemberExpression expressionBody = (MemberExpression)memberExpression.Body;
        OnPropertyChanged(expressionBody.Member.Name);
    }

    public override string ToString()
    {
        return Content;
    }
}

并将其用作ObservableCollection&lt;Tag&gt; Tags。然后像这样绑定到它

<TextBox Text="{Binding Content, Mode=TwoWay}" Tag="{Binding}"/>

我实际上在字符串数组列中从 postgres 数据库填充并保存到其中,所以我需要与 string[] 相互转换。这些是我的转化:

string[] array = note.Tags.Select(item => item.Content).ToArray();
note.Tags = new ObservableCollection<Tag>((array.Select(item => new Tag() { Content = item }).ToList()));

【讨论】:

    猜你喜欢
    • 2023-03-29
    • 2016-06-18
    • 1970-01-01
    • 2011-03-05
    • 1970-01-01
    • 2018-08-10
    • 1970-01-01
    • 2011-04-27
    • 1970-01-01
    相关资源
    最近更新 更多