使用双向绑定和TabControl的奇怪行为

时间:2013-08-12 12:26:19

标签: wpf binding tabcontrol

在我的应用程序中,我有以下TabControl:

<TabControl ItemsSource="{Binding MyItemsSource}"
            ContentTemplate="{StaticResource ResourceKey=MyContentTemplate}"
            IsSynchronizedWithCurrentItem="True" />

以下是使用的ContentTemplate:

<DataTemplate x:Key="MyContentTemplate">
    <Canvas>
        <TextBox Text="{Binding Path=MyFirstText, Mode=TwoWay}" />
        <TextBox Text="{Binding Path=MySecondText, Mode=TwoWay}" />
    </Canvas>
</DataTemplate>

还有ItemsSource:

public ObservableCollection<MyData> MyItemsSource { get; set; }

public class MyData
{
    public string MyFirstText { get; set; }
    public string MySecondText { get; set; }
}

请考虑这种情况:

  • 选择第一个标签
  • 在第一个TextBox中输入一些文字
  • 选择第二个标签
  • 选择第一个选项卡:在第一个选项卡的TextBox中输入的文本消失(因为未应用绑定)

另一种情况:

  • 选择第一个标签
  • 在第一个TextBox中输入一些文字
  • 选择第二个TextBox(或更改焦点除了更改标签之外的任何内容)
  • 选择第二个标签
  • 选择第一个选项卡:仍然显示输入的文本(因为已应用绑定)

这是正常行为吗?或者我做错了什么?谢谢。

3 个答案:

答案 0 :(得分:2)

这是因为TextBox的更新触发器默认设置为LostFocus。将其更改为PropertyChanged,它应该可以工作:

<TextBox Text="{Binding Path=MyFirstText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />

UpdateSourceTrigger:http://msdn.microsoft.com/en-us/library/system.windows.data.updatesourcetrigger.aspx

答案 1 :(得分:1)

它可能与聚焦元素有关,并且在选项卡之间切换时不会触发OnLostFocus事件。尝试使用UpdateSourceTriger属性更改绑定:

<DataTemplate x:Key="MyContentTemplate">
    <Canvas>
        <TextBox Text="{Binding Path=MyFirstText, UpdateSourceTrigger=PropertyChanged}" />
        <TextBox Text="{Binding Path=MySecondText, UpdateSourceTrigger=PropertyChanged}" />
    </Canvas>
</DataTemplate>

此外,您无需指定twoway模式,因为在wpf中它是默认模式。

答案 2 :(得分:0)

问题是更改标签时不会触发LostFocus,您可以像前面提到的那样将UpdateSourceTrigger更改为PropertyChanged,但我更喜欢扩展TabControl并手动触发LostFocus。这样我就不必将UpdateSourceTrigger = PropertyChanged添加到我的Tab中的每个TextBox。我也避免每次按键都更新viewmodel。

这是此处提到的解决方案的衍生物。 WPF: Data bound TabControl doesn't commit changes when new tab is selected

public class SmartTabControl : TabControl
{
    protected override void OnSelectionChanged(SelectionChangedEventArgs e)
    {
        if (Keyboard.FocusedElement is TextBox)
            Keyboard.FocusedElement.RaiseEvent(new RoutedEventArgs(LostFocusEvent));

        base.OnSelectionChanged(e);
    }
}