单击选项卡时,WPF控件失去焦点

时间:2013-04-05 16:03:33

标签: wpf binding prism tabcontrol lostfocus

在tabcontrol上我有几个tabpages,在其中一个选项卡上,内容中有一个文本框。

此文本框是使用简单的Path = PropertyName和UpdateSourceTrigger = LostFocus绑定的内容。我使用LostFocus的原因是我捕获文本框的丢失焦点事件并可能重新格式化文本。这是一个“时间”文本框,如果输入“0900”,我想重新格式化为“09:00”。当我按Tab键移动到下一个控件时,这部分工作得很好,但是如果我输入“0900”然后按其中一个选项卡,我点击丢失的焦点并重新格式化文本框中的值,但绑定永远不会被调用来更新我的对象。当我返回选项卡时,该值被消隐(或重置为对象上的原始值)

更改标签页时,为什么文本框不会触发绑定更新的任何想法?

注意:这也发生在常规文本框中,该文本框连接到丢失焦点事件。这似乎与单击选项卡有关。

[[新增代码]] 更多说明: 1.我在选项卡上动态创建选项卡和控件(不确定是否与它有关) 2.我正在使用Prism库

MainWindow Xaml

<Window.Resources>
    <DataTemplate DataType="{x:Type ctrls:myTextBoxDef}">
        <Grid Width="300">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" MinWidth="100" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="28" />
            </Grid.RowDefinitions>
            <TextBlock Grid.Column="0"
                   HorizontalAlignment="Stretch"
                   VerticalAlignment="Center"
                   Text="{Binding LabelText}" />

            <TextBox Grid.Column="1"
                 HorizontalAlignment="Stretch"
                 VerticalAlignment="Center"
                 Text="{Binding DocValue,
                                Mode=TwoWay,
                                ValidatesOnDataErrors=True,
                                UpdateSourceTrigger=LostFocus}"
                         />
        </Grid>
    </DataTemplate>
</Window.Resources>


<Grid>
    <TabControl HorizontalAlignment="Stretch"
                VerticalAlignment="Stretch"
                HorizontalContentAlignment="Stretch"
                VerticalContentAlignment="Stretch"
                IsTabStop="False"                 
                ItemsSource="{Binding Tabs, Mode=OneWay}"
                SelectedItem="{Binding SelectedTab,
                                Mode=TwoWay,
                                NotifyOnSourceUpdated=True}"
                >
        <TabControl.ItemTemplate>
            <DataTemplate>
                <Grid>  
                    <TextBlock Margin="18,14,22,0"                                       
                               Text="{Binding HeaderText}" />
                </Grid>
            </DataTemplate>
        </TabControl.ItemTemplate>
        <!--  Content  -->
        <TabControl.ContentTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition Width="Auto" />
                    </Grid.ColumnDefinitions>

                    <AdornerDecorator Grid.Column="0">
                        <ItemsControl Grid.Column="0"
                                          HorizontalAlignment="Stretch"
                                          VerticalAlignment="Stretch"
                                          IsTabStop="False"
                                          ItemsSource="{Binding Controls,
                                                                Mode=OneWay}">
                            <ItemsControl.ItemsPanel>
                                <ItemsPanelTemplate>
                                    <WrapPanel Grid.Column="0"
                                                   Margin="10,5,0,0"
                                                   HorizontalAlignment="Stretch"
                                                   VerticalAlignment="Stretch"
                                                   Orientation="Vertical" />
                                </ItemsPanelTemplate>
                            </ItemsControl.ItemsPanel>
                        </ItemsControl>
                    </AdornerDecorator>
                    </Grid>
                </DataTemplate>
            </TabControl.ContentTemplate>
        </TabControl>
    </Grid>
</Window>

主窗口代码背后

public partial class MainWindow : Window
{
    private DataContextObject obj = new DataContextObject();
    public MainWindow()
    {
        InitializeComponent();

        myTextBoxDef txt1 = new myTextBoxDef(obj, "Textbox 1", "TAB1TextBox1");
        myTextBoxDef txt1b = new myTextBoxDef(obj, "Textbox 1 value", "TAB1TextBox1");

        myTextBoxDef txt2 = new myTextBoxDef(obj, "Textbox 2", "TAB1TextBox2");
        myTextBoxDef txt2b = new myTextBoxDef(obj, "Textbox 2 value", "TAB1TextBox2");

        obj.Tabs.Add(new myTabDef("Tab 1", new ObservableCollection<myTextBoxDef>() { txt1, txt2 }));
        obj.Tabs.Add(new myTabDef("Tab 2", new ObservableCollection<myTextBoxDef>() { txt1b, txt2b }));

        obj.SelectedTab = obj.Tabs[0];

        this.DataContext = obj;
    }
}

支持对象

public class DataContextObject : NotificationObject
{
    List<myTabDef> _tabs = new List<myTabDef>();
    public List<myTabDef> Tabs
    {
        get
        {
            return _tabs;
        }
    }

    private myTabDef _item;
    public myTabDef SelectedTab
    {
        get
        { return _item; }
        set
        {
            _item = value;
            this.RaisePropertyChanged("SelectedItem");
        }
    }

    private string _txt1 = "";
    public string TAB1TextBox1
    {
        get { return _txt1; }
        set
        {
            _txt1 = value;
            this.RaisePropertyChanged("TAB1TextBox1");
        }
    }

    private string _txt2 = "";
    public string TAB1TextBox2
    {
        get { return _txt2; }
        set
        {
            _txt2 = value;
            this.RaisePropertyChanged("TAB1TextBox2");
        }
    }

    private string _txt3 = "";
    public string TAB2TextBox1
    {
        get { return _txt3; }
        set
        {
            _txt3 = value;
            this.RaisePropertyChanged("TAB2TextBox1");
        }
    }
}

public class myTabDef
{
    public myTabDef(string tabText, ObservableCollection<myTextBoxDef> controls)
    {
        HeaderText = tabText;
        _left = controls;
    }

    public string HeaderText { get; set; }

    private ObservableCollection<myTextBoxDef> _left = new ObservableCollection<myTextBoxDef>();
    public ObservableCollection<myTextBoxDef> Controls
    {
        get
        {
            return _left;
        }
    }
}

public class myTextBoxDef : NotificationObject
{
    public myTextBoxDef(NotificationObject bound, string label, string bindingPath)
    {
        LabelText = label;
        Path = bindingPath;
        BoundObject = bound;

        BoundObject.PropertyChanged += BoundObject_PropertyChanged;
    }

    public string LabelText
    {
        get;
        set;
    }

    public NotificationObject BoundObject
    {
        get;
        set;
    }

    public string DocValue
    {
        get
        {
            return PropInfo.GetValue(BoundObject, null) as string;
        }
        set
        {
            PropInfo.SetValue(BoundObject, value, null);
        }
    }

    protected virtual void BoundObject_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        if (e.PropertyName.Equals(Path))
        {
            this.RaisePropertyChanged("DocValue");
        }
    }

    public string Path
    {
        get;
        set;
    }

    private PropertyInfo pi = null;
    protected PropertyInfo PropInfo
    {
        get
        {
            if (pi == null && BoundObject != null && !string.IsNullOrEmpty(Path))
            {
                PropertyInfo[] properties = BoundObject.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);

                pi = properties.Where((prop) => string.Compare(prop.Name, Path, true) == 0).FirstOrDefault();
            }

            return pi;
        }
    }
}

1 个答案:

答案 0 :(得分:2)

我们找到了解决方案。我过来了这组帖子

https://groups.google.com/forum/#!topic/wpf-disciples/HKUU61A5l74

他们谈论一个名为TabControlEx的控件。在底部(从底部开始的第5个),您将看到Sacha Barber的帖子,其中有一个带有示例的zip文件。

它解决了我们遇到的所有问题。

这里还有另一个链接,其中发布了Class的代码

http://updatecontrols.codeplex.com/discussions/214434