我做了一個用戶控件,我把它叫做InputTextBox,用戶可以點擊控件後所編輯現有案文:用戶控件失去鍵盤焦點
<Grid>
<TextBox Name="box"
Text="{Binding RelativeSource={RelativeSource AncestorType=local:InputTextBlock}, Path=Text, Mode=TwoWay}"
Visibility="Hidden"
LostKeyboardFocus="box_LostKeyboardFocus"
KeyDown="box_KeyDown"/>
<Button Name="block"
Background="Transparent"
BorderThickness="0"
Click="block_Click">
<Button.Content>
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=local:InputTextBlock}, Path=Text}" />
</Button.Content>
</Button>
</Grid>
當用戶單擊該按鈕下面callack是使用:
private void block_Click(object sender, RoutedEventArgs e)
{
StartEdit();
}
public void StartEdit()
{
box.Visibility = Visibility.Visible;
block.Visibility = Visibility.Hidden;
box.CaretIndex = box.Text.Length;
Keyboard.Focus(box);
}
在控件中處理了兩個更重要的事件。第一種是當控件失去鍵盤焦點:
private void box_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
box.Visibility = Visibility.Hidden;
block.Visibility = Visibility.Visible;
}
,另一種是當用戶按下TAB或ENTER鍵:
private void box_KeyDown(object sender, KeyEventArgs e)
{
Key key = e.Key;
if (key == Key.Enter || key == Key.Tab)
{
RoutedEventArgs args = new RoutedEventArgs(KeyExitEvent, this, e.Key);
RaiseEvent(args);
}
}
這引起了我註冊這個控件調用一個簡單的路由事件KeyExit。
因此,基本上,它就像這個控件有兩個「模式」:用戶可以通過簡單地點擊控件就可以激活的「編輯模式」,以及用戶可以通過給予任何其他模式返回的「查看模式」控制UI鍵盤焦點。
在我的UI中,我有一堆堆棧面板,裏面有一堆這些控件 - 每一個都被包裝在我創建的類中,與概念類似於ListViewItem。這個想法是,當用戶在堆棧面板中的某個項目內處於編輯模式時,單擊TAB或ENTER鍵,面板中的下一個控件將進入編輯模式。
所以,我有以下事件的回調:
private void item_KeyExit(object sender, RoutedEventArgs e)
{
FrameworkElement obj = e.OriginalSource as FrameworkElement;
if (obj != null)
{
var listItem = VisualTreeHelperUtils.FindFirstAncestorOfType<MyListItem>(obj);
if (listItem != null)
{
int itemIndex = stackPanelList.Children.IndexOf(listItem);
MyListItem nextItem = null;
if (itemIndex == ucSortableList.Children.Count - 1)
{
nextItem = stackPanelList.Children[itemIndex+1] as MyListItem;
}
if (nextItem != null)
{
var item = nextItem.DataContent; // property I made in MyListItem that gives access to the class it wraps
InputTextBlock block = item as InputTextBlock;
if (block != null)
{
block.StartEdit();
}
}
}
}
}
一切正常調用,但馬上這一切完成後,原來的項目,這是我標籤出來的,獲取鍵盤焦點回來,導致堆棧中的項目不處於編輯模式。因此,例如,如果堆棧中的第一項處於編輯模式,則一旦用戶點擊Tab鍵,堆棧中的第二項進入編輯模式,但第一項立即返回鍵盤焦點。任何人都可以理解爲什麼發生這種情況?