Databinding A Progress bar to a view model - c#

I have a simple progress bar and status message textblock bound to a view model that should iterate in a foreach statement. it works fine in testing when a put a MessageBox in the foreach but if I take out the MessageBox the only status that's being captured is the last iteration and I can't determine what I need to do to correct that.
ViewModel -
public class ExampleViewModel : INotifyPropertyChanged
{
public RelayCommand<IList> Submit { get; }
private KeyValuePair<Model, string[]> _selectedItem;
public KeyValuePair<Model, string[]> SelectedItem
{
get => _selectedItem;
set
{
_selectedItem = value;
RaisePropertyChanged(nameof(SelectedItem));
}
}
public ExampleViewModel()
{
Submit = new RelayCommand<IList>(ExecuteSubmit);
}
private void ExecuteSubmit(IList selectedItems)
{
string[] examples = new string[] {"a", "b", "c"};
double percentAge = 100/examples.Count;
if (examples.Count > 0)
{
foreach (var ex in examples)
{
CurrentProgress = CurrentProgress + percentAge;
MessageBox.Show("Step " + ex); // Status and Progress Bar update when this isn't commented out
// Thread.Sleep(1000);
StatusMessages = "Option " + ex;
}
}
return;
}
#region Status Fields
private string _statusMessages;
public string StatusMessages
{
get => _statusMessages;
set
{
if (_statusMessages != value)
{
_statusMessages = value;
RaisePropertyChanged(nameof(StatusMessages));
}
}
}
private double _currentProgress;
public double CurrentProgress
{
get => _currentProgress;
set
{
if (_currentProgress != value)
{
_currentProgress = value;
RaisePropertyChanged(nameof(CurrentProgress));
}
}
}
#endregion
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new
PropertyChangedEventArgs(propertyName));
}
}
}
XAML -
<ProgressBar Value="{Binding CurrentProgress, Mode=OneWay}"
Margin="5,5" Height="10" Width="240" HorizontalAlignment="Left"/>
<TextBlock Margin="5,5" Height="15" Width="240" TextWrapping="Wrap"
Foreground="Red"
Text="{Binding StatusMessages}"></TextBlock>

Calling Thread.Sleep(1000); on UI thread is wrong.. It freezes the UI and once the freeze ends it will start a new freeze so it could not even update any of the UI elements that are bound with the properties.. You can use DispatcherTimer instead
Replace
foreach (var ex in examples)
{
CurrentProgress = CurrentProgress + percentAge;
MessageBox.Show("Step " + ex); // Status and Progress Bar update when this isn't commented out
// Thread.Sleep(1000);
StatusMessages = "Option " + ex;
}
With
var timer = new DispatcherTimer
{
Interval = TimeSpan.FromSeconds(1)
};
int ticksCount = 0;
var ticksLimit = examples.Count;
timer.Tick += (_, _) =>
{
ticksCount++;
if (ticksCount > ticksLimit)
timer.Stop();
else
{
var ex = examples[ticksCount - 1];
CurrentProgress = CurrentProgress + percentAge;
StatusMessages = "Option " + ex;
}
};
timer.Start();

Related

Slider do not work after changing track NAudio

I have slider as trackbar for soundtrack timeline.Soundtrack play from web using NAudion. All code using from NAudio WPF example.I changed only accessibility modifiers.First time when I start play first track all works good.But if I change to next track, slider still in start.And changing only if I click Pause then Play.
For fully understand:
First track - slider works and moves.
Change to the next track - slider at the beginning and doesn't move. But it begins to move after pressing Pause, then Play. It immediately moves to the place where the playback is at the moment and continues normal operation. And so with each following track.
Code of VM for PlayerUserControl:
public class AudioControlVM : ViewModelBase, IDisposable
{
private AudioModel _currentSong;
public AudioModel CurrentSong { get { return _currentSong; } set { _currentSong = value; RaisePropertyChanged("CurrentSong"); } }
private string inputPath, songName;
private string defaultDecompressionFormat;
public IWavePlayer wavePlayer { get; set; }
private WaveStream reader;
public RelayCommand PlayCommand { get; set; }
public RelayCommand PauseCommand { get; set; }
public RelayCommand StopCommand { get; set; }
public DispatcherTimer timer = new DispatcherTimer();
private double sliderPosition;
private readonly ObservableCollection<string> inputPathHistory;
private string lastPlayed;
public AudioControlVM()
{
inputPathHistory = new ObservableCollection<string>();
PlayCommand = new RelayCommand(() => Play());
PauseCommand = new RelayCommand(() => Pause());
StopCommand = new RelayCommand(Stop, () => !IsStopped);
timer.Interval = TimeSpan.FromMilliseconds(500);
timer.Tick += TimerOnTick;
}
public bool IsPlaying => wavePlayer != null && wavePlayer.PlaybackState == PlaybackState.Playing;
public bool IsStopped => wavePlayer == null || wavePlayer.PlaybackState == PlaybackState.Stopped;
public IEnumerable<string> InputPathHistory => inputPathHistory;
const double SliderMax = 10.0;
private void TimerOnTick(object sender, EventArgs eventArgs)
{
if (reader != null)
{
sliderPosition = reader.Position * SliderMax / reader.Length;
RaisePropertyChanged("SliderPosition");
}
}
public double SliderPosition
{
get => sliderPosition;
set
{
if (sliderPosition != value)
{
sliderPosition = value;
if (reader != null)
{
var pos = (long)(reader.Length * sliderPosition / SliderMax);
reader.Position = pos; // media foundation will worry about block align for us
}
RaisePropertyChanged("SliderPosition");
}
}
}
private bool TryOpenInputFile(string file)
{
bool isValid = false;
try
{
using (var tempReader = new MediaFoundationReader(file))
{
DefaultDecompressionFormat = tempReader.WaveFormat.ToString();
InputPath = file;
isValid = true;
}
}
catch (Exception e)
{
}
return isValid;
}
public string DefaultDecompressionFormat
{
get => defaultDecompressionFormat;
set
{
defaultDecompressionFormat = value;
RaisePropertyChanged("DefaultDecompressionFormat");
}
}
public string SongName { get => songName; set
{
songName = value;
RaisePropertyChanged("SongName");
} }
public string InputPath
{
get => inputPath;
set
{
if (inputPath != value)
{
inputPath = value;
AddToHistory(value);
RaisePropertyChanged("InputPath");
}
}
}
private void AddToHistory(string value)
{
if (!inputPathHistory.Contains(value))
{
inputPathHistory.Add(value);
}
}
public void Stop()
{
if (wavePlayer != null)
{
wavePlayer.Stop();
}
}
public void Pause()
{
if (wavePlayer != null)
{
wavePlayer.Pause();
RaisePropertyChanged("IsPlaying");
RaisePropertyChanged("IsStopped");
}
}
public void Play()
{
if (String.IsNullOrEmpty(InputPath))
{
return;
}
if (wavePlayer == null)
{
CreatePlayer();
}
if (lastPlayed != inputPath && reader != null)
{
reader.Dispose();
reader = null;
}
if (reader == null)
{
reader = new MediaFoundationReader(inputPath);
lastPlayed = inputPath;
wavePlayer.Init(reader);
}
wavePlayer.Play();
RaisePropertyChanged("IsPlaying");
RaisePropertyChanged("IsStopped");
timer.Start();
}
private void CreatePlayer()
{
wavePlayer = new WaveOutEvent();
wavePlayer.PlaybackStopped += WavePlayerOnPlaybackStopped;
RaisePropertyChanged("wavePlayer");
}
private void WavePlayerOnPlaybackStopped(object sender, StoppedEventArgs stoppedEventArgs)
{
if (reader != null)
{
SliderPosition = 0;
//reader.Position = 0;
timer.Stop();
}
if (stoppedEventArgs.Exception != null)
{
}
RaisePropertyChanged("IsPlaying");
RaisePropertyChanged("IsStopped");
}
public void PlayFromUrl(string url, string songname)
{
Stop();
inputPath = url;
SongName = songname;
Play();
}
public void Dispose()
{
wavePlayer?.Dispose();
reader?.Dispose();
}
}
XAML of player:
<Grid>
<StackPanel Orientation="Horizontal">
<Button Content="Play" Command="{Binding PlayCommand}" VerticalAlignment="Center" Width="75" />
<Button Content="Pause" Command="{Binding PauseCommand}" VerticalAlignment="Center" Width="75" />
<Button Content="Stop" Command="{Binding PlayCommand}" VerticalAlignment="Center" Width="75" />
<Slider VerticalAlignment="Center" Value="{Binding SliderPosition, Mode=TwoWay}" Maximum="10" Width="400" />
<TextBlock Text="{Binding SongName, FallbackValue=Test}" Foreground="White"/>
</StackPanel>
</Grid>
</UserControl>
VM code that sends data for a new track:
public class AudioModel
{
public string Artist { get; set; }
public string SongName { get; set; }
public int Duration { get; set; }
public string URL { get; set; }
public RelayCommand PlayThisAudioCommand
{
get;
private set;
}
public AudioModel()
{
PlayThisAudioCommand = new RelayCommand(() => PlayThis());
}
private void PlayThis()
{
if (URL != null)
{
TestVM.AudioConrol.PlayFromUrl(URL, SongName);
}
else;
}
}
It looks like you may have a multi-threading issue with your timer. The sequence of events appears to be:
First Track
PlayFromUrl() calls Play() which starts the file playing, and starts the timer.
Slider updates as expected
Second Track
When you call PlayFromUrl() it:
Calls Stop() (which stops the wavePlayer, and stops the timer)
Calls Play() (which starts the wavePlayer, and starts the timer)
Then the wavePlayer.PlaybackStopped event is raised (due to your earlier call to wavePlayer.Stop()), which calls WavePlayerOnPlaybackStopped(), which stops the timer.
The important point here is the order that Play() and WavePlayerOnPlaybackStopped() are called. It's very likely that the events are happening in the order above - as the wavePlayer raises the PlaybackStopped event on another thread.
In short - that WavePlayerOnPlaybackStopped() is stopping your timer after Play() started it, which is why your slider isn't updating. Pressing Pause then Play will restart the timer, which is why the slider begins updating after pausing.
You could test this by temporarily commenting out the code in WavePlayerOnPlaybackStopped(), which should fix the issue - although your slider will not reset to zero when the track reaches the end or stops.
NOTE: The cause of the delay between calling wavePlayer.Stop() and the wavePlayer.PlaybackStopped event being raised is due to nAudio using a dedicated thread to handle playback. When you call Stop(), it must finish processing the current audio buffer before actually stopping - which in most cases will result in a delay of a few milliseconds.
You can see this in action in the WaveOutEvent's DoPlayback method: https://github.com/naudio/NAudio/blob/master/NAudio/Wave/WaveOutputs/WaveOutEvent.cs#L147

I can't get my value to update using INotifyPropertyChanged

So I am learning WPF by making a yatzee game, and I'm getting somewhere. But now I can not understand why I my "current roll" counter won't update in the View. I made the Dices work, and the roll dices button gives my dices new values - and this is updated in the view. But my "Current roll" variable will not. This is what I've done so far.
// CurrentRoll.cs
public class CurrentRoll : INotifyPropertyChanged
{
public int _roll;
public int Roll
{
get { return _roll; }
set
{
if (value != _roll)
{
_roll = value;
OnPropertyChanged("Roll");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
Then this is my DiceModelView. When I hit my "Roll Dices" button I get new values on all my dices as long as they are left unchecked. I also increment the _currentRoll variable, and only allow new rolls as long as _currentRoll still is less than 3. This logic works, the variable works, but it's representation in the View does not. I've also changed its initial value to other values just to see that my binding works, and it does.
public class DiceModelView : INotifyPropertyChanged
{
Die _die;
public CurrentRoll _currentRoll;
public event PropertyChangedEventHandler PropertyChanged;
public ObservableCollection<Die> myDices { get; set; }
public ICommand RollCommand { get; set; }
public DiceModelView()
{
myDices = new ObservableCollection<Die>()
{
new Die { Id = 0, Roll = 0, Checked = false },
new Die { Id = 1, Roll = 0, Checked = false },
new Die { Id = 2, Roll = 0, Checked = false },
new Die { Id = 3, Roll = 0, Checked = false },
new Die { Id = 4, Roll = 0, Checked = false }
};
_currentRoll = new CurrentRoll();
_currentRoll._roll = 0;
RollCommand = new Command (executeMethod, canexecuteMethod);
}
public bool canexecuteMethod(object parameter)
{
return true;
}
private void executeMethod(object parameter)
{
var r = new Random();
if (_currentRoll._roll < 3)
{
foreach (Die d in myDices)
{
if (d.Checked == false)
{
d.Roll = r.Next(1, 7);
}
}
}
_currentRoll._roll++;
}
private void NotifyPropertyChanged(String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public Die die
{
get { return _die; }
set { _die = value; }
}
public CurrentRoll currentRoll
{
get { return _currentRoll; }
set { _currentRoll = value;
NotifyPropertyChanged("currentRoll");
}
}
Finally, this is the XAML code I use:
<Window.DataContext>
<local:DiceModelView/>
</Window.DataContext>
<StackPanel>
<TextBlock Text="{Binding currentRoll.Roll, UpdateSourceTrigger=PropertyChanged}"/>
<ListView x:Name="DiceView" ItemsSource="{Binding myDices}" Width="500" HorizontalContentAlignment="Center" >
<ListView.ItemTemplate>
<DataTemplate >
<CheckBox Content="{Binding Roll}" IsChecked="{Binding Checked}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Button Content="Roll the dices!" Command="{Binding RollCommand}"/>
</StackPanel>
</Window>
You need to update the Roll property, not the _role field.
_roll should be private anyway.
Just think about it: You are raising the property changed event in the property setter, so this only get's executed when you set the value of the property.

wpf - One ViewModel for dynamic Tabs

Is it possible to have one ViewModel for multiple dynamic Tabs? Meaning that, whenever I create a new tab, it should use the same instance of ViewModel so I can retrieve information and also prevent each Tab from sharing data/showing the same data.
The setting I'm thinking of using it in would be for a payroll application where each employee's payslip can be updated from each tab. So the information should be different in each Tab.
Is this possible?
Update: Added code
MainViewModel where Tabs Collection is handled:
public ObservableCollection<WorkspaceViewModel> Workspaces { get; set; }
public MainViewModel()
{
Workspaces = new ObservableCollection<WorkspaceViewModel>();
Workspaces.CollectionChanged += Workspaces_CollectionChanged;
}
void Workspaces_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null && e.NewItems.Count != 0)
foreach (WorkspaceViewModel workspace in e.NewItems)
workspace.RequestClose += this.OnWorkspaceRequestClose;
if (e.OldItems != null && e.OldItems.Count != 0)
foreach (WorkspaceViewModel workspace in e.OldItems)
workspace.RequestClose -= this.OnWorkspaceRequestClose;
}
private void OnWorkspaceRequestClose(object sender, EventArgs e)
{
CloseWorkspace();
}
private DelegateCommand _exitCommand;
public ICommand ExitCommand
{
get { return _exitCommand ?? (_exitCommand = new DelegateCommand(() => Application.Current.Shutdown())); }
}
private DelegateCommand _newWorkspaceCommand;
public ICommand NewWorkspaceCommand
{
get { return _newWorkspaceCommand ?? (_newWorkspaceCommand = new DelegateCommand(NewWorkspace)); }
}
private void NewWorkspace()
{
var workspace = new WorkspaceViewModel();
Workspaces.Add(workspace);
SelectedIndex = Workspaces.IndexOf(workspace);
}
private DelegateCommand _closeWorkspaceCommand;
public ICommand CloseWorkspaceCommand
{
get { return _closeWorkspaceCommand ?? (_closeWorkspaceCommand = new DelegateCommand(CloseWorkspace, () => Workspaces.Count > 0)); }
}
private void CloseWorkspace()
{
Workspaces.RemoveAt(SelectedIndex);
SelectedIndex = 0;
}
private int _selectedIndex = 0;
public int SelectedIndex
{
get { return _selectedIndex; }
set
{
_selectedIndex = value;
OnPropertyChanged("SelectedIndex");
}
}
WorkspaceViewModel:
public PayslipModel Payslip { get; set; }
public WorkspaceViewModel()
{
Payslip = new PayslipModel();
SaveToDatabase = new DelegateCommand(Save, () => CanSave);
SelectAll = new DelegateCommand(Select, () => CanSelect);
UnSelectAll = new DelegateCommand(UnSelect, () => CanUnSelect);
}
public ICommand SaveToDatabase
{
get; set;
}
private bool CanSave
{
get { return true; }
}
private async void Save()
{
try
{
MessageBox.Show(Payslip.Amount.ToString());
}
catch (DbEntityValidationException ex)
{
foreach (var en in ex.EntityValidationErrors)
{
var exceptionDialog = new MessageDialog
{
Message = { Text = string.Format("{0}, {1}", en.Entry.Entity.GetType().Name, en.Entry.State) }
};
await DialogHost.Show(exceptionDialog, "RootDialog");
foreach (var ve in en.ValidationErrors)
{
exceptionDialog = new MessageDialog
{
Message = { Text = string.Format("{0}, {1}", ve.PropertyName, ve.ErrorMessage) }
};
await DialogHost.Show(exceptionDialog, "RootDialog");
}
}
}
catch (Exception ex)
{
var exceptionDialog = new MessageDialog
{
Message = { Text = string.Format("{0}", ex) }
};
await DialogHost.Show(exceptionDialog, "RootDialog");
}
}
public event EventHandler RequestClose;
private void OnRequestClose()
{
if (RequestClose != null)
RequestClose(this, EventArgs.Empty);
}
private string _header;
public string Header
{
get { return _header; }
set
{
_header = value;
OnPropertyChanged("Header");
}
}
Payroll UserControl where WorkspaceViewModel is DataContext:
public Payroll()
{
InitializeComponent();
DataContext = new WorkspaceViewModel();
}
Payroll.xaml Tabcontrol:
<dragablz:TabablzControl ItemsSource="{Binding Workspaces}" SelectedIndex="{Binding SelectedIndex}" BorderBrush="{x:Null}">
<dragablz:TabablzControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Header}"/>
</DataTemplate>
</dragablz:TabablzControl.ItemTemplate>
<dragablz:TabablzControl.ContentTemplate>
<DataTemplate>
<ContentControl Margin="16">
<local:TabLayout DataContext="{Binding Path=Payslip, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" x:Name="tabLayout"/>
</ContentControl>
</DataTemplate>
</dragablz:TabablzControl.ContentTemplate>
</dragablz:TabablzControl>
This works as expected, each tab displays different info and bindings work okay. However, I'm unable to retrieve the info in the MessageBox.
I'm not sure if I totally understand your question but if you need a Window with a tabcontrol, in which each tab refers to an employee, then you will have to bind the ItemsSource of the tabcontrol to a list of the ViewModel.
It is not possible to bind all tabpages to the same instance because then the tabpages will all do the same, and show the same information.
I couldn't get it to work the way I had it, so I placed the save button inside the view that has DataContext set to where employee's info are loaded and got it to work from there, since it directly accesses the properties.
ViewModels should have a 1:1 relationship with the model. In your TabControl's DataContext, let's say you have properties like:
public ObservableCollection<EmployeeViewModel> Employees {get;set;}
public EmployeeViewModel CurrentEmployee
{
get { return _currentEmployee;}
set
{
_currentEmployee = value;
OnPropertyChanged("CurrentEmployee");
}
}
where Employees is bound to ItemsSource of the TabControl, and CurrentEmployee to CurrentItem. To create a new tab:
var employee = new Employee();
var vm = new EmployeeViewModel(employee);
Employees.Add(vm);
CurrentEmployee = vm;
If you want a save button outside of the TabControl, just set its DataContext to CurrentEmployee.
I hope this helps!
Edit:
Two things I think are causing problems:
Payroll.xaml should be bound to MainViewModel since that's where the Workspaces collection is.
Do not instantiate ViewModels in your view's code behind. Use a DataTemplate instead (see this question).
Take a look at Josh Smith's MVVM demo app (source code)

How to use DynamicResource of Label content?

I try to development a WPF application with "DynamicResource", so I have i Label in XAML file like this:
<Window.Resources>
<local:BindingClass x:Key="myDataSource"/>
<local:UtilityGioco x:Key="myUtilityGame" />
</Window.Resources>
<Label x:Name="labelTempo" DataContext="{DynamicResource myUtilityGame}" Content="{Binding Path=tempoEsecuzioneEsercizio}" FontFamily="Arial" FontSize="21"
Foreground="Gray" Grid.Column="0" Grid.Row="1" FontWeight="Bold"
Margin="15,40,0,0"/>
In the UtilityGioco class i have this code:
public string tempoEsecuzioneEsercizio
{
set;
get;
}
private void displayTimer(object sender, EventArgs e)
{
try
{
// code goes here
//Console.WriteLine(DateTime.Now.Hour.ToString() + ":");
if (timeSecond == 59)
{
timeSecond = 0;
timeMinutes++;
}
//se il contatore dei minuti รจ maggiore di 0, devo mostrare una scritta altrimenti un altra
if (timeMinutes > 0)
{
tempoEsecuzioneEsercizio = timeMinutes + " min " + ++timeSecond + " sec";
}
else
{
tempoEsecuzioneEsercizio = ++timeSecond + " sec";
}
}
catch (Exception ex)
{
log.Error("MainWindow metodo: displayTimer ", ex);
}
}
The "displayTimer" method is called every time, but the content of Label is blank.
Can you help me?
In your UtilityGioco class implement INotifyPropertyChanged interface and notify about the change in the setter of tempoEsecuzioneEsercizio property.
Example:
private string _tempoEsecuzioneEsercizio;
public string tempoEsecuzioneEsercizio
{
set
{
_tempoEsecuzioneEsercizio = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("tempoEsecuzioneEsercizio"));
}
}
get { return _tempoEsecuzioneEsercizio; }
}
Maybe you can use INotifyPropertyChanged:http://msdn.microsoft.com/it-it/library/system.componentmodel.inotifypropertychanged(v=vs.110).aspx
public event PropertyChangedEventHandler PropertyChanged;
private string _tempoEsecuzioneEsercizio;
public string tempoEsecuzioneEsercizio
{
set
{
if (_tempoEsecuzioneEsercizio != value)
{
this._tempoEsecuzioneEsercizio = value;
this.OnNotifyPropertyChange("tempoEsecuzioneEsercizio");
}
}
get { return _tempoEsecuzioneEsercizio; }
}
public void OnNotifyPropertyChange(string propertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}

UI hangs when adding large data in pivot item for WP8

I am creating a dynamic pivot. In which I have binded a collection to pivot ItemSouce. When the selectionchange event is fired I am calling a process which takes some time and the update the ObservableCollection which in turn update the UI. I am using async and await but still the application UI hangs.
Let me know what is the issue. Looking for a very quick reply.
CODE:
private void CraetePivotItems()
{
for (int count = 0; count < 100; count++)
{
EntityDetail item = new EntityDetail();
item.HeaderTitle = "Header " + count;
item.Name = string.Empty;
this.Detaildata.Add(item);
}
}
private async Task<string> CreateUserControlForPivotItem(int selectedIndex)
{
for (int count = 0; count < 1000000000; count++)
{
}
switch (selectedIndex)
{
case 0:
return "Item 1";
case 1:
return "Item 2";
case 2:
return "Item 3";
default:
return "Item N";
}
}
private void pvtItmCities_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
CraetePivotItems();
this.pvtItmCities.ItemsSource = this.Detaildata;
}
private async void pvtItmCities_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (sender != null)
{
////// Create the user control for the selected pivot item
string pivotItemContentControl = await CreateUserControlForPivotItem(((Pivot)sender).SelectedIndex);
(this.Detaildata[((Pivot)sender).SelectedIndex] as EntityDetail).Name = pivotItemContentControl;
//((System.Windows.Controls.ContentControl)((sender as Pivot).SelectedItem)).Content = pivotItemContentControl;
}
}
Class
internal class EntityDetail : INotifyPropertyChanged
{
private string headerTitle = String.Empty;
public string HeaderTitle
{
get
{
return this.headerTitle;
}
set
{
if (value != this.headerTitle)
{
this.headerTitle = value;
NotifyPropertyChanged();
}
}
}
private string name = String.Empty;
public string Name
{
get
{
return this.name;
}
set
{
if (value != this.name)
{
this.name = value;
NotifyPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
// This method is called by the Set accessor of each property.
// The CallerMemberName attribute that is applied to the optional propertyName
// parameter causes the property name of the caller to be substituted as an argument.
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
XAML:
<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Key="HeaderTemplateSample">
<TextBlock Text="{Binding HeaderTitle}" Foreground="White"/>
</DataTemplate>
<DataTemplate x:Key="ItemTemplateSample">
<local:PivotItem1Content Foreground="White"/>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
<phone:Pivot x:Name="pvtItmCities"
HeaderTemplate="{StaticResource HeaderTemplateSample}"
ItemTemplate="{StaticResource ItemTemplateSample}"
SelectionChanged="pvtItmCities_SelectionChanged" Loaded="pvtItmCities_Loaded" Title="pivot demo" LoadingPivotItem="OnLoadingPivotItem">
</phone:Pivot>
What is the issue??
i suggest that you create manually a separate thread and assign it to the function and it will update the UI thread when its finish. using Async Await doesn't mean that this is going to be on a different thread.
http://msdn.microsoft.com/en-us/library/windowsphone/develop/cc221403%28v=vs.105%29.aspx
this link show you how to assign a background worker (thread) to complete your tasks
i hope this will help you

Categories