开发者

How do I know that a Silverlight control has been displayed?

开发者 https://www.devze.com 2023-03-06 16:54 出处:网络
I have a list box displaying the names of help topics which can be added to and the names of the topics changed. Originally it was just displaying strings, but to get the inline editing working I chan

I have a list box displaying the names of help topics which can be added to and the names of the topics changed. Originally it was just displaying strings, but to get the inline editing working I changed it to use a custom type consisting of a string and an InEdit property so the UI can determine whether to display the TextBlock or 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 is an ObservableCollection<EditableHelpTopic>.

SelectedPageId is a string.

boolToVisibilityConverter is a converter that does what it says.

What works:

  • Adding a topic creates a new item and adds it to the list and put the item in to edit mode.
  • Double clicking on an existing item puts that item into edit mode sets the focus to the TextBox and selects all the text so it can be overwritten.
  • When the TextBox loses focus the edit is saved and the display returns to the TextBlock.

What doesn't work:

  • When a new topic is added the TextBox should have focus and the text selected so the user can enter a new name.

So my question is is there a point in the code or an event where I know that the TextBox has been created and is visible so I can set focus and select its contents. I've tried hooking into the SelectionChanged event but when that fires the TextBox hasn't yet been displayed. I also added an event to the OnAddTopicExecute method in the view model which I handled in the view, but again that fired before the TextBox was visible.


Below is the code that supports the above XAML. I've tried to cut it down, but there still seems to be a lot of it, so you can skip this if you're not interested ;)

Code behind:

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);
    }
}

View Model:

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

where DelegateCommand is an implemetation of ICommand.

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

Definitions:

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


It turned out to be simpler than I thought.

I just needed to add a Loaded event handler to the TextBox:

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();
    }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号