I have done the following in XAML
<ItemsControl x:Name="CursorLegendIC" Grid.Column="0" Grid.Row="1" ItemsSource="{Binding}" Margin="0,0" Padding="0,0,0,-300">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<Ellipse Width="8" Height="8" HorizontalAlignment="Left" Margin="0,0,0,-16" Fill="{Binding SeriesColor, Converter={StaticResource ColorToBrushConverter}}" />
<TextBlock Margin="10,0,0,0" HorizontalAlignment="Left" TextWrapping="Wrap" FontSize="11" FontWeight="Bold" Foreground="{Binding SeriesColor, Converter={StaticResource ColorToBrushConverter}}" Text="{Binding SeriesName}"/>
<TextBlock FontSize="11" HorizontalAlignment="Left" TextWrapping="Wrap" Margin="10,-3,0,4" Foreground="{Binding SeriesColor, Converter={StaticResource ColorToBrushConverter}}" Text="{Binding YValue, StringFormat=\{0:0.000\}}" />
<TextBlock FontSize="11" HorizontalAlignment="Left" TextWrapping="Wrap" Margin="10,-8,0,4" Foreground="{Binding SeriesColor, Converter={StaticResource ColorToBrushConverter}}" Text="{Binding RenderableSeries.YAxisId}"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
And I have set the data context accordingly:
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
CursorLegendIC.DataContext = this.RolloverSeriesWithoutFirstData;
}
And set the Observable collection property as public
public ObservableCollection<SeriesInfo> RolloverSeriesWithoutFirstData
{
get
{
ObservableCollection<SeriesInfo> Temp = rolloverModifier.SeriesData.SeriesInfo;
return Temp;
}
}
But binding is still not working!
It seems to only take the binding at the first instance.
When data collection is later added, the binding changes does not seem to take effect.
Any help? Thanks
Your issue is that the instance (the entire collection) of the property SeriesInfo changes, without the owner of RolloverSeriesWithoutFirstData (lets call it MyWindow) is notified of the change. Either make your own event, or implemenet INotifyPropertyChanged. I've made an example with INPC:
class SeriesData : INotifyPropertyChanged
{
private ObservableCollection<SeriesInfo> _seriesInfo;
public ObservableCollection<SeriesInfo> SeriesInfo
{
set{ SetProperty(ref _seriesInfo, value); }
}
public event PropertyChangedEventHandler PropertyChanged;
private bool SetProperty<T>(ref T storage, T value, [CallermemberName] string propertyName = null)
{
if(Equals(storage,value)) return false;
storage = value;
var handler = PropertyChanged;
if(handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
return true;
}
}
In MyWindow you does this:
class MyWindow : Window, INotifyPropertyChanged
{
public ObservableCollection<SeriesInfo> RolloverSeriesWithoutFirstData
{
get{ return rolloverModifier.SeriesData.SeriesInfo; }
}
public event PropertyChangedEventHandler PropertyChanged;
public MyWindow()
{
// Get rolloverModifier
rolloverModifier.SeriesData.PropertyChanged += SeriesDataPropertyChanged;
}
private void SeriesDataPropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch(e.PropertyName)
{
case "SeriesInfo":
RaisePropertyChanged("RolloverSeriesWithoutFirstData");
break;
}
}
private void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if(handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
Now SeriesData notifies it's listeners (our case MyWindow) that one of it's properties has changed value. MyWindow will then relay that notification to it's listeners (the bindings) that it's property: RolloverSeriesWithoutFirstData has changed.
Assuming that you are using MVVM pattern, you should remove the code behind and just bind to your ObservableCollection :
<ItemsControl x:Name="CursorLegendIC" Grid.Column="0" Grid.Row="1" ItemsSource="{Binding RolloverSeriesWithoutFirstData}" Margin="0,0" Padding="0,0,0,-300">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<Ellipse Width="8" Height="8" HorizontalAlignment="Left" Margin="0,0,0,-16" Fill="{Binding SeriesColor, Converter={StaticResource ColorToBrushConverter}}" />
<TextBlock Margin="10,0,0,0" HorizontalAlignment="Left" TextWrapping="Wrap" FontSize="11" FontWeight="Bold" Foreground="{Binding SeriesColor, Converter={StaticResource ColorToBrushConverter}}" Text="{Binding SeriesName}"/>
<TextBlock FontSize="11" HorizontalAlignment="Left" TextWrapping="Wrap" Margin="10,-3,0,4" Foreground="{Binding SeriesColor, Converter={StaticResource ColorToBrushConverter}}" Text="{Binding YValue, StringFormat=\{0:0.000\}}" />
<TextBlock FontSize="11" HorizontalAlignment="Left" TextWrapping="Wrap" Margin="10,-8,0,4" Foreground="{Binding SeriesColor, Converter={StaticResource ColorToBrushConverter}}" Text="{Binding RenderableSeries.YAxisId}"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
+Questions: what is rolloverModifier ? is rolloverModifier.SeriesData.SeriesInfo modified?
You just need to implement the INotifyPropertyChanged Interface in the class that you defined your RolloverSeriesWithoutFirstData property in. As that property has no setter, you will have to manually raise the NotifyPropertyChanged event whenever you update the collection:
(pseudo code):
rolloverModifier.SeriesData.SeriesInfo = DataAccess.GetNewCollection();
NotifyPropertyChanged("RolloverSeriesWithoutFirstData");
Change
CursorLegendIC.DataContext = this.RolloverSeriesWithoutFirstData
for
CursorLegendIC.ItemsSource= this.RolloverSeriesWithoutFirstData
Or as You can see in the above answer, remove code behind and use clear mvvm
Related
I have an ObservableCollection<string> bound to a ItemsControl as the ItemsSource, the binding works fine from the VM to the View but if I change the content of the binding in the TextBox it will not update the ObservableCollection that it is bound to.
I can't seem to work out why, does anyone know why this is?
Here is my code:
<ItemsControl ItemsSource="{Binding Metrics, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Grid.Column="1" Grid.Row="1" Margin="0, 20, 0, 0">
<ItemsControl.ItemTemplate>
<DataTemplate>
<WrapPanel Orientation="Horizontal">
<TextBox Name="CalibrationNameTB" Grid.Column="1" Text="{Binding ., UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Style="{StaticResource baseStyle}" Margin="0, 1" Padding="5, 1" Width="270" FontSize="12"/>
</WrapPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.Template>
<ControlTemplate TargetType="ItemsControl" >
<StackPanel Orientation="Horizontal" >
<ItemsPresenter />
</StackPanel>
</ControlTemplate>
</ItemsControl.Template>
</ItemsControl>
You can't update a string because it's immutable.
What you should do is to replace the ObservableCollection<string> with an ObservableCollection<YourType> where YourType is a class with a public string property that you can get or set:
class YourType : INotifyPropertyChanged
{
private string _theString;
public string TheString
{
get { return _theString; }
set { _theString = value; NotifyPropertyChanged(); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Then you bind to this property in your XAML markup:
<WrapPanel Orientation="Horizontal">
<TextBox Name="CalibrationNameTB" Grid.Column="1" Text="{Binding TheString, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource baseStyle}" Margin="0, 1" Padding="5, 1" Width="270" FontSize="12"/>
</WrapPanel>
In first column i have list of groups ("First","Second"). In second column i have 5 button's. I want to enable or disable group of button's after choosing their group in first column. How to do this in MVVM pattern?
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new Data();
}
}
public class Data
{
public List<string> Items { get; set; }
public Data()
{
Items = new List<string>();
Items.Add("First");
Items.Add("Second");
}
}
Xaml:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<ListView ItemsSource="{Binding Items}" Grid.Column="0">
<ListView.ItemTemplate>
<DataTemplate>
<Label Content="{Binding .}"></Label>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Button Content="First" Grid.Column="1" HorizontalAlignment="Left" Height="30" Margin="21,24,0,0" VerticalAlignment="Top" Width="76" IsEnabled="False"/>
<Button Content="Second" Grid.Column="1" HorizontalAlignment="Left" Height="30" Margin="102,48,0,0" VerticalAlignment="Top" Width="76" IsEnabled="True"/>
<Button Content="First" Grid.Column="1" HorizontalAlignment="Left" Height="30" Margin="33,83,0,0" VerticalAlignment="Top" Width="76" IsEnabled="False"/>
<Button Content="Second" Grid.Column="1" HorizontalAlignment="Left" Height="30" Margin="126,93,0,0" VerticalAlignment="Top" Width="76" IsEnabled="True" RenderTransformOrigin="1.088,-0.075"/>
<Button Content="Second" Grid.Column="1" HorizontalAlignment="Left" Height="30" Margin="93,186,0,0" VerticalAlignment="Top" Width="76" IsEnabled="True"/>
</Grid>
Create your VM classes like:
public class Data:INotifyPropertyChanged
{
public ObservableCollection<MyRecord> Items
{
get{
return _items;
}
set{
_items=value;
OnProperyChanged("Items")
}
}
public Data()
{
Items = new ObservableCollection<MyRecord>()
{
new MyRecord(){Title:"First",IsEnable:false}),
new MyRecord(){Title:"Second",IsEnable:false})
};
}
//---------------------------------------------------------------
public event PropertyChangedEventHandler PropertyChanged;
private void OnProperyChanged(string propertyName)
{
if (PropertyChanged != null)
{
var handler= PropertyChanged ;
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
public class MyRecord:INotifyPropertyChanged
{
private int _title;
private bool _isEnable;
public int Title
{
get
{
return _title;
}
set
{
_title= value;
OnProperyChanged("Title")
}
}
public bool IsEnable
{
get
{
return _isEnable;
}
set
{
_isEnable= value;
OnProperyChanged("IsEnable")
}
}
//---------------------------------------------------------------
public event PropertyChangedEventHandler PropertyChanged;
private void OnProperyChanged(string propertyName)
{
if (PropertyChanged != null)
{
var handler= PropertyChanged ;
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Now in your Xaml bind the IsEnabled property of each Button to appropriate property...
You can write the following code with BooleanToVisibilityConverter:
//First add BooleanToVisibilityConverter to the window resources
// When you know Items[0] is FIRST use some code like this>>
IsEnabled="{Binding Items[0].IsEnable, converter={StaticResource BooleanToVisibilityConverter}}"
Sample:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<ListView ItemsSource="{Binding Items}" Grid.Column="0">
<ListView.ItemTemplate>
<DataTemplate>
<Label Content="{Binding .}"></Label>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Button Content="First"
IsEnabled="{Binding Items[0].IsEnable, converter={StaticResource BooleanToVisibilityConverter}}"
Grid.Column="1" HorizontalAlignment="Left" Height="30" Margin="21,24,0,0" VerticalAlignment="Top" Width="76"/>
<Button Content="Second"
IsEnabled="{Binding Items[1].IsEnable, converter={StaticResource BooleanToVisibilityConverter}}"
Grid.Column="1" HorizontalAlignment="Left" Height="30" Margin="102,48,0,0" VerticalAlignment="Top" Width="76"/>
<Button Content="First"
IsEnabled="{Binding Items[0].IsEnable, converter={StaticResource BooleanToVisibilityConverter}}"
Grid.Column="1" HorizontalAlignment="Left" Height="30" Margin="33,83,0,0" VerticalAlignment="Top" Width="76"/>
<Button Content="Second"
IsEnabled="{Binding Items[1].IsEnable, converter={StaticResource BooleanToVisibilityConverter}}"
Grid.Column="1" HorizontalAlignment="Left" Height="30" Margin="126,93,0,0" VerticalAlignment="Top" Width="76" RenderTransformOrigin="1.088,-0.075"/>
<Button Content="Second"
IsEnabled="{Binding Items[1].IsEnable, converter={StaticResource BooleanToVisibilityConverter}}"
Grid.Column="1" HorizontalAlignment="Left" Height="30" Margin="93,186,0,0" VerticalAlignment="Top" Width="76"/>
</Grid>
OK, every things is good until this step. Now if you make IsEnable property of each item to TRUE, then the buttons must be Enabled And conversely. To perform it you can:
Write a Command in your Data class and make a binding between each List
item and the command.
Use ListView.SelectionChanged event to make IsEnable property of the Clicked item to TRUE. Note: Now, the type of each item in the ListView is MyRecord.
The best solution to your problem is to use a IValueConverter, in this example I created a convert named GroupToBooleanConverter receiving the value of the selected item in the first column by the parameter value and the button group by parameter 'parameter ', the code converter is below:
public class GroupToBooleanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var selectedGroup = value as string;
var buttonGroup = (string)parameter;
return buttonGroup.Equals(selectedGroup);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Now in its XAML you must reference the namespace of your turn, in my example the namespace convert is namespaceOfConverter, and must be imported to convert through it, is as follows:
xmlns:converters="clr-namespace:namespaceOfConverter"
Place the attribute up on your Window tag in your XAML. Now you must reference the convert, putting it in the Window resources:
<Window.Resources>
<converters:GroupToBooleanConverter x:Key="GroupToBoolean" />
</Window.Resources>
I called your ListView of lsvGroups:
<ListView ItemsSource="{Binding Items}" x:Name="lsvGroups" Grid.Column="0">
....
Now just use the converter in your buttons, performing binding in the property IsEnabled:
IsEnabled="{Binding SelectedItem, ElementName=lsvGroups,Converter={StaticResource GroupToBoolean},ConverterParameter=First}"
OBs: In the place of First you put the name of group associate with button.
To start off, I have a listbox that is trying to accept a UserControl as the DataTemplate:
<ListBox VerticalAlignment="Stretch" Name="GeneralMcmView" Grid.Column="0" HorizontalAlignment="Stretch" >
<ListBox.ItemTemplate>
<DataTemplate DataType="local:GeneralMcmMessage">
<local:GeneralMcmMessage />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
With the contents of the usercontrol looking like:
<ContentControl FontFamily="Segoe UI" VerticalAlignment="Stretch" FontSize="10">
<Grid VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<StackPanel VerticalAlignment="Stretch" Orientation="Horizontal" Grid.Row="0">
<TextBlock Name="MessageDateTime" Text="{Binding ElementName=_this, Path=TimeStamp, StringFormat=MM/dd/yyyy h:mm:ss.fff tt \'GMT\' (zzz)}" />
<TextBlock Name="MessageTypeLabel" Margin="15,0,5,0" Text="Type:"/>
<TextBlock Name="MessageType" Text="{Binding ElementName=_this, Path=Type}" />
</StackPanel>
<StackPanel VerticalAlignment="Stretch" Orientation="Horizontal" Grid.Row="1">
<TextBlock Name="MessageNameLabel" Margin="0,0,5,0" Text="Message Name:" />
<TextBlock Name="MessageNameValue" Text="{Binding ElementName=_this, Path=MessageName}" TextWrapping="Wrap" />
</StackPanel>
<StackPanel VerticalAlignment="Stretch" Orientation="Vertical" Grid.Row="2">
<TextBlock Name="MessageLabel" Text="Message:"/>
<TextBlock Name="Message" Margin="10,0,0,0" Text="{Binding ElementName=_this, Path=MessageContent}" />
</StackPanel>
</Grid>
</ContentControl>
I then create a couple messages, all with different data (The Listbox's ItemSource is bound to the GeneralMessages ObservableCollection):
GeneralMcmMessage newMsg = new GeneralMcmMessage()
{
MessageId = e.McmMessageViewInfo.Id,
TimeStamp = e.McmMessageViewInfo.MessageDateTime,
Type = e.McmMessageViewInfo.MessageType.ToString(),
MessageName = e.McmMessageViewInfo.MessageName,
MessageContent = e.McmMessageViewInfo.Message.ToString()
};
GeneralMessages.Add( newMsg );
During runtime I interrogate the Items property of the listbox and all the data looks correct, however all I see in the listbox are entries of the GeneralMcmMessage User Control with default data values. Any ideas as to why?
Also, FWIW I am using INotifyPropertyChanged in the usercontrol class:
public partial class GeneralMcmMessage : UserControl, INotifyPropertyChanged
{
private Constants.PiuModule piuModule = Constants.PiuModule.MCM;
private string className = "GeneralMcmMessage";
/// <summary>
/// Event for notifying listeners that a property changed. Part of INotifyPropertyChanged
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
public int MessageId { get; set; }
private DateTime timeStamp;
public DateTime TimeStamp
{
get
{
return timeStamp;
}
set
{
timeStamp = value;
OnNotifyPropertyChanged( "TimeStamp" );
}
}
You're saying that the DataTemplate to display a GeneralMcmMessage is to instantiate new GeneralMcmMessage.
<DataTemplate DataType="local:GeneralMcmMessage">
<local:GeneralMcmMessage />
</DataTemplate>
I'd recommend instead of making a collection of your UserControl to make a collection of your model object instead, and bind to the properties within that within your UserControl.
Either way though - the object you created in code will be the DataContext for the one you created in XAML so removing the ElementName=_this should bind appropriately. Try this simplified XAML in your UserControl instead.
<StackPanel VerticalAlignment="Stretch" Orientation="Horizontal" Grid.Row="0">
<TextBlock Name="MessageDateTime" Text="{Binding TimeStamp, StringFormat=MM/dd/yyyy h:mm:ss.fff tt \'GMT\' (zzz)}" />
<TextBlock Name="MessageTypeLabel" Margin="15,0,5,0" Text="Type:"/>
<TextBlock Name="MessageType" Text="{Binding Type}" />
</StackPanel>
<StackPanel VerticalAlignment="Stretch" Orientation="Horizontal" Grid.Row="1">
<TextBlock Name="MessageNameLabel" Margin="0,0,5,0" Text="Message Name:" />
<TextBlock Name="MessageNameValue" Text="{Binding MessageName}" TextWrapping="Wrap" />
</StackPanel>
<StackPanel VerticalAlignment="Stretch" Orientation="Vertical" Grid.Row="2">
<TextBlock Name="MessageLabel" Text="Message:"/>
<TextBlock Name="Message" Margin="10,0,0,0" Text="{Binding MessageContent}" />
</StackPanel>
You don’t post all code of GeneralMcmMessage hence I don’t know if you set DataContext in user control for example in constructor of GeneralMcmMessage.
I tried replicate your problem.
User control GeneralMcmMessage code behind
public partial class GeneralMcmMessage : UserControl, INotifyPropertyChanged
{
private int _messageId;
public int MessageId
{
get
{
return _messageId;
}
set
{
_messageId = value;
OnPropertyChanged("MessageId");
}
}
private DateTime _timeStamp;
public DateTime TimeStamp
{
get
{
return _timeStamp;
}
set
{
_timeStamp = value;
OnPropertyChanged("TimeStamp");
}
}
public GeneralMcmMessage()
{
InitializeComponent();
//don’t set data context here
//DataContext = this;
}
}
User control GeneralMcmMessage XAML
<StackPanel>
<TextBlock Margin="5" FontSize="20" Text="{Binding Path=MessageId}"/>
<TextBlock Margin="5" FontSize="20" Text="{Binding Path=TimeStamp}"/>
</StackPanel>
User control GeneralMcmMessage usage
public partial class MainWindow : Window, INotifyPropertyChanged
{
private ObservableCollection<GeneralMcmMessage> _generalMessages;
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
public ObservableCollection<GeneralMcmMessage> GeneralMcmMessages
{
get { return _generalMessages; }
set
{
_generalMessages = value;
OnPropertyChanged("GeneralMcmMessages");
}
}
private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
{
GeneralMcmMessages = new ObservableCollection<GeneralMcmMessage>();
for (int i = 0; i < 10; i++)
{
var newMsg = new GeneralMcmMessage
{
MessageId = i,
TimeStamp = DateTime.Now,
};
GeneralMcmMessages.Add(newMsg);
}
}
}
User control GeneralMcmMessage usage XAML
<ListBox x:Name="ListBox"
Margin="5"
ItemsSource="{Binding Path=GeneralMcmMessages}">
<ListBox.ItemTemplate>
<DataTemplate DataType="stackoverflow:GeneralMcmMessage">
<stackoverflow:GeneralMcmMessage/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
If this not solve your problem could you please post all GeneralMcmMessage?
If you want I can upload sample project for you.
Thank you
I have the following class which will be the binding source:
public class Timeline : Canvas, INotifyPropertyChanged
{
public static readonly DependencyProperty TimeTextBindingPropProperty;
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string name)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
public double TimeTextBindingProp
{
get { return (double)GetValue(TimeTextBindingPropProperty); }
set
{
SetValue(TimeTextBindingPropProperty, value);
OnPropertyChanged("TimeTextBindingProp");
}
}
static Timeline()
{
TimeTextBindingPropProperty = DependencyProperty.Register("TimeTextBindingProp", typeof(double), typeof(Timeline));
}
}
Then I set the binding between a textbox's Text property and timeline's TimeTextBindingProp property at my main window:
private void InitTextBinding()
{
timeTextBinding = new Binding();
timeTextBinding.Mode = BindingMode.OneWay;
timeTextBinding.Source = timeline;
timeTextBinding.Path = new PropertyPath("TimeTextBindingProp");
timeTextBinding.Converter = new TimeTextConverter();
BindingOperations.SetBinding(this.timeTextBox, TextBox.TextProperty, timeTextBinding);
}
PropertyChanged handler of timeline remains null even after binding is set and timeline is rendered. What am I doing wrong?
Edit:
I declare timeTextBox and timeline in xaml as follows:
<StackPanel Orientation="Horizontal" Margin="0,10,0,5" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBox Name="timeTextBox" Margin="0,0,20,0" VerticalAlignment="Center" HorizontalContentAlignment="Center" Height="20"
FontFamily="Tahoma" FontSize="14" BorderBrush="White" Background="White"/>
<Button Name="playButton" Style="{StaticResource buttonStyle}" Click="PlayButton_Click" Margin="0,0,5,0" HorizontalAlignment="Center"
VerticalAlignment="Center">
Play
</Button>
<Button Name="stopButton" Style="{StaticResource buttonStyle}" Click="StopButton_Click" Margin="0,0,20,0" HorizontalAlignment="Center"
VerticalAlignment="Center">
Stop
</Button>
<Slider Name="controlSlider" Height="Auto" Width="200" HorizontalAlignment="Center" VerticalAlignment="Center" IsEnabled="False">
<Slider.ToolTip>
<TextBlock Style="{StaticResource textStyleTextBlock}">Time Slider</TextBlock>
</Slider.ToolTip>
</Slider>
</StackPanel>
<ScrollViewer Name="scrollViewer" Margin="0,0,10,20" Height="500" HorizontalAlignment="Stretch" VerticalAlignment="Center" Focusable="False"
HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<StackPanel>
<UI:FittingCanvas x:Name="containerCanvas">
<timelinePanel:Timeline x:Name="timeline" TimeCursorEnabled="True" TimeMode="Minutes" Canvas.Left="0" Canvas.Top="0" Canvas.ZIndex="0" Visibility="Hidden"
CursorAnimBoundaryChanged="Timeline_CursorAnimBoundaryChanged" AnimationCompleted="Timeline_AnimationCompleted"/>
</UI:FittingCanvas>
<Canvas x:Name="waveFormCanvas" Height="80" Margin="0,10,0,0"/>
</StackPanel>
</ScrollViewer>
Does your code update timeTextBox.Text any other way than setting the timeTextBinding? Maybe you set timeTextBox.Text to some value directly in the code-behind, or you have some other binding hooked up to it?
Because timeTextBinding is only OneWay, such a change can't be written back to TimeTextBindingProp, and the binding will simply be overwritten and deleted (without any warning), and timeline.PropertyChanged will be reset to null.
<ListBox Height="434" HorizontalAlignment="Left" Margin="6,238,0,0" Name="listBox1" VerticalAlignment="Top" Width="432" DataContext="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Name}" Margin="4" Foreground="{StaticResource PhoneAccentBrush}"></TextBlock>
<StackPanel Orientation="Horizontal" Margin="4">
<TextBlock Text="Set" Margin="16" Foreground="{StaticResource PhoneAccentBrush}" />
<TextBlock Text="Weight" Margin="16" Foreground="{StaticResource PhoneAccentBrush}" />
<TextBlock Text="Reps" Margin="10,16,0,16" Foreground="{StaticResource PhoneAccentBrush}" />
</StackPanel>
<ListBox Name="setsAndReps" Height="auto" Width="auto" ItemsSource="{Binding Sets}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBox Text="{Binding SetNumber}"/>
<TextBox Text="{Binding Weight}"/>
<TextBox Text="{Binding Reps}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The outer listbox's item source is being set to an observable collection of a user defined class called excercise
public class excercise : IComparable, IEquatable<excercise>, INotifyPropertyChanged
{
string name;
int max;
int NUM_SETS;
ObservableCollection<set> sets;
public event PropertyChangedEventHandler PropertyChanged;
public string Name
{
get { return this.name; }
set { this.name = value; }
}
public excercise(string name)
{
this.name = name;
this.NUM_SETS = 0;
this.sets = new ObservableCollection<set>();
}
public ObservableCollection<set> Sets
{
get{return this.sets; }
}
public ObservableCollection<set> getSets()
{
return this.sets;
}
}
The properties in the inner list box are from the set class but none of them are being displayed and I am not sure what the problem is.
your first listbox doesn't have any itemsource set and the datacontext is set to an empty binding (both on line 1 of your code)