Matas Vaitkevicius
Matas Vaitkevicius

Reputation: 61401

Setting WPF Delay from code in MVVM

I am working on WPF application (.NET 4.5), and using Caliburn.Micro. I am generating a list of questions and answers in ListBox answers can be of 3 types (RadioButtons, DropDowns and Textboxes). When question is being answered, property triggers change in ViewModel and next question is being added.
Problem I ran into is when symbol is being added to Textbox it immediately fires property change.

public string TextValue
    {
        get { return _textValue; }
        set
        {
            _textValue = value;
            NotifyOfPropertyChange(() => TextValue);
        }
    }

Normally (for non dynamically generated controls) I could delay it by using 'new'

<TextBlock Text="{Binding TextValue, Delay=500}"/>

but since I am generating these questions I am not sure on how to proceed with this.

Is there a way to set Delay to generated control from code behind?

UPDATE:
this is how XAML looks like. List is being populated with questions on runtime (from DB), and questions do change based on previous answers, so there is no way of setting anything in XAML.

<UserControl x:Class="Corp.Conveyancing.Desktop.Views.Probate.PifWFlowQuestionsView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:probate="clr-namespace:Corp.Conveyancing.Desktop.Views.Probate"
             mc:Ignorable="d" >
    <Grid Margin="10" Width="600" Height="400" >
        <ListBox x:Name="QuestionItems" Grid.Row="0" BorderThickness="0" HorizontalContentAlignment="Stretch" ScrollViewer.CanContentScroll="true" ScrollViewer.VerticalScrollBarVisibility="Visible" Height="380" Width="580" probate:ListBoxExtenders.AutoScrollToEnd="True" >
            <ListBox.ItemContainerStyle >
                <Style TargetType="ListBoxItem">
                    <Setter Property="Focusable" Value="False"/>
                </Style>
            </ListBox.ItemContainerStyle>
        </ListBox>
    </Grid>
</UserControl>

UPDATE2:
I have BindableCollection<QuestionItemViewModel> which is property in PifWFlowQuestionsViewModel to which I am adding only first question and then based on answer I am adding more questions,a nd based on those adding more and so on.

public class PifWFlowQuestionsViewModel : PropertyChangedBase
{
    private BindableCollection<QuestionItemViewModel> _questionItems =
        new BindableCollection<QuestionItemViewModel>();

    public BindableCollection<QuestionItemViewModel> QuestionItems
    {
        get { return _questionItems; } 
        set
        {
            _questionItems = value;
            NotifyOfPropertyChange(() => QuestionItems);
        }
    }
}

Upvotes: 1

Views: 1001

Answers (2)

Matas Vaitkevicius
Matas Vaitkevicius

Reputation: 61401

This is how I ended up solving it, might be not THE solution, but it was quick and easy.
I realize that it does not answer to the title of the question, however it does provide solution to the problem above, and I am sure someone will find this useful.

public class QuestionTextViewModel : QuestionItemViewModel
{
    private Timer Timer { get; set; }

    public QuestionTextViewModel(IEventAggregator eventAggregator, TransactionDetail transactionDetail)
        : base(transactionDetail)
    {
        _eventAggregator = eventAggregator;
        TransactionDetailId = transactionDetail.TransactionDetailId;
        this.Timer = new Timer(1500) {AutoReset = false};
        this.Timer.Elapsed += TextValueTimer_Elapsed;
    }

    public string TextValue
    {
        get { return _textValue; }
        set
        {
            _textValue = value;
            this.Timer.Stop();
            this.Timer.Start();
        }
    }

    private void TextValueTimer_Elapsed(object sender, ElapsedEventArgs e)
    {
        NotifyOfPropertyChange(() => TextValue);
    }
}

Upvotes: 1

toadflakz
toadflakz

Reputation: 7944

You should be using an ItemTemplateSelector on the ListBox and basing what type of DataTemplate is used for the QuestionItemViewModel based on the returned properties for the new item.

It would definitely be possible to do the control generation in XAML then as you're specifying the DataTemplate content.

Upvotes: 0

Related Questions