如何知道已显示 Silverlight 控件

本文关键字:Silverlight 控件 显示 何知道 | 更新日期: 2023-09-27 17:56:48

我有一个列表框,显示可以添加到的帮助主题的名称以及更改的主题的名称。最初它只是显示字符串,但为了让内联编辑工作,我将其更改为使用由字符串和InEdit属性组成的自定义类型,以便 UI 可以确定是显示TextBlock还是TextBox

XAML:

<ListBox ItemsSource="{Binding HelpTopics, Mode=TwoWay}"
         SelectedValuePath="Description"
         SelectedValue="{Binding SelectedPageId, Mode=TwoWay}"
         SelectionChanged="ListBox_SelectionChanged">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Grid>
                <TextBlock Text="{Binding Description, Mode=TwoWay}" 
                           VerticalAlignment="Center"
                           MouseLeftButtonUp="TopicTextBlock_MouseLeftButtonUp"
                           Visibility="{Binding InEdit, Converter={StaticResource boolToVisibilityConverter}, ConverterParameter=contra}"/>
                <TextBox Text="{Binding Description, Mode=TwoWay}" 
                         Visibility="{Binding InEdit, Converter={StaticResource boolToVisibilityConverter}, ConverterParameter=pro}"
                         LostFocus="EditTopicTextBox_LostFocus"
                         HorizontalAlignment="Stretch" VerticalAlignment="Center"/>
            </Grid>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>
<Button Margin="5" Content="Add Topic" Command="{Binding AddTopicCommand}"/>

HelpTopics是一个ObservableCollection<EditableHelpTopic>.
SelectedPageId是一个string.
boolToVisibilityConverter是一个按照它所说的去做的转换器。

什么有效:

  • 添加主题会创建一个新项目并将其添加到列表中,然后将该项目置于编辑模式。
  • 双击现有项目会将该项目置于编辑模式,将焦点设置为TextBox并选择所有文本,以便可以覆盖它。
  • TextBox失去焦点时,将保存编辑内容,并返回到TextBlock

什么不起作用:

  • 添加新主题时,TextBox应具有焦点并选择文本,以便用户可以输入新名称。

所以我的问题是代码或事件中是否有某个点我知道TextBox已经创建并且可见,以便我可以设置焦点并选择其内容。我已经尝试挂接到SelectionChanged事件,但是当触发时,TextBox尚未显示。我还向视图模型中的 OnAddTopicExecute 方法添加了一个事件,我在视图中处理了该事件,但同样在TextBox可见之前触发了该事件。


下面是支持上述 XAML 的代码。我试图削减它,但似乎仍然有很多,所以如果你不感兴趣,你可以跳过这个;)

代码隐藏:

private DateTime lastClickTime = DateTime.MinValue;
private Point lastClickPosition;
private void TopicTextBlock_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
    UIElement element = sender as UIElement;
    if ((DateTime.Now - this.lastClickTime).TotalMilliseconds > 300)
    {
        this.lastClickPosition = e.GetPosition(element);
        this.lastClickTime = DateTime.Now;
    }
    else
    {
        Point position = e.GetPosition(element);
        if (Math.Abs(this.lastClickPosition.X - position.X) < 4 && Math.Abs(this.lastClickPosition.Y - position.Y) < 4)
        {
            var textBlock = sender as TextBlock;
            var editableHelpTopic = textBlock.DataContext as EditableHelpTopic;
            editableHelpTopic.InEdit = true;
            var parent = textBlock.Parent as Grid;
            TextBox textBox = parent.Children.First(c => c.GetType() == typeof(TextBox)) as TextBox;
            textBox.Focus();
            textBox.SelectAll();
        }
    }  
}
private void EditTopicTextBox_LostFocus(object sender, RoutedEventArgs e)
{
    var textBox = sender as TextBox;
    var editableHelpTopic = textBox.DataContext as EditableHelpTopic;
    editableHelpTopic.InEdit = false;
    if (!textBox.Text.Equals(editableHelpTopic.Description))
    {
        this.editViewModel.RenameTopic(textBox.Text);
    }
}

查看模型:

public EditViewModel()
{
    ...
    this.AddTopicCommand = new DelegateCommand(this.OnAddTopicExecute, this.OnAddTopicCanExecute);
    ...
}

其中DelegateCommandICommand的实现.

private void OnAddTopicExecute(object parameter)
{
    var newTopic = new EditableHelpTopic
        {
            Description = "NewTopic",
            InEdit = true
        };
    this.HelpTopics.Add(newTopic);
    this.SelectedPageId = newTopic.Description;
}

定义:

public class EditableHelpTopic : INotifyPropertyChanged
{
    public bool InEdit { ... }
    public string Description { ... }
}

如何知道已显示 Silverlight 控件

事实证明,它比我想象的要简单。

我只需要向TextBox添加一个Loaded事件处理程序:

private void EditTopicTextBox_Loaded(object sender, RoutedEventArgs e)
{
    var textBox = sender as TextBox;
    var editableHelpTopic = textBox.DataContext as EditableHelpTopic;
    if (editableHelpTopic.InEdit)
    {
        textBox.Focus();
        textBox.SelectAll();
    }
}