I made an UserControl that contains three toggle buttons that are each bound to different items of the same ObservableCollection. The UserControl is later used inside a Popup.
For some reason, when I toggle one of them, on an other instance of the UserControl within an other popup, it is also toggled.
The three ToggleButtons inside the UserControl look like this :
<DockPanel DockPanel.Dock="Top" LastChildFill="False" Margin="0, 0, 0, 8">
<TextBlock DockPanel.Dock="left" Margin="0" Text="ROTATION" Foreground="{StaticResource BaseText}" VerticalAlignment="Center"/>
<ToggleButton DockPanel.Dock="Right" Height="25" Width="25" Tag="3" IsChecked="{Binding RotationAxis[2], ElementName=RotationPanel, Converter={StaticResource BoolToString}, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Click="ToggleButton_Click" Content="Z"/>
<ToggleButton IsChecked="{Binding RotationAxis[1], ElementName=RotationPanel, Converter={StaticResource BoolToString}, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
<ToggleButton IsChecked="{Binding RotationAxis[0], ElementName=RotationPanel, Converter={StaticResource BoolToString}, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
</DockPanel>
They are bound to this DependencyProperty :
public static readonly DependencyProperty RotationAxisProperty =
DependencyProperty.Register("RotationAxis", typeof(ObservableCollection<string>), typeof(RotationSelector), new PropertyMetadata(new ObservableCollection<string> { "True", "True", "True" }));
[Bindable(true)]
public ObservableCollection<string> RotationAxis
{
get { return (ObservableCollection<string>)this.GetValue(RotationAxisProperty); }
set { this.SetValue(RotationAxisProperty, value); }
}
The UserControl is then used twice in my app :
<Popup x:Name="SpritePopupRotation">
<CMiX:RotationSelector x:Name="SpriteSelectedRotation" RotationAxis="{Binding Datacontext.SpriteRotationAxis, ElementName=Ch_Parameters, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" AxisChanged="RotationSelector_AxisChanged"/>
</Popup>
<Popup x:Name="MaskPopupRotation">
<CMiX:RotationSelector x:Name="MaskSelectedRotation" RotationAxis="{Binding Datacontext.MaskRotationAxis, ElementName=Ch_Parameters, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" AxisChanged="RotationSelector_AxisChanged"/>
</Popup>
Now, when I start my app, the three ToggleButtons from one UserControl look like they are bound to the other three of the other instance of the UserControl.
Why is this happening ?
Related
I'm working on a punch clock application as a way of learning C#, XAML, and databases. Right now, my GUI isn't behaving how I would like it to.
I have a TextBlock for each of my buttons like what is shown after Start Shift.
However, when the dates are not valid, the TextBlocks are hidden. I've been able to show and hide the visibility of these how I want to. But, when I skip Start Lunch and End Lunch and go straight to End Shift, the End Shift TextBlock shows up after the Start Lunch Button as if the Start Lunch and End Lunch TextBlocks don't exist.
I've looked online and found that the visibility trait reserves space when it is hidden and doesn't reserve space when it is collapsed, but I am using hidden and it still isn't reserving space. My code is shown below.
HomeView.xaml
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<!--Left column buttons-->
<StackPanel Grid.Column="0" Margin="10">
<Button Width="140" Content="Start Shift" Command="{Binding startShiftCommand}"
IsEnabled="{Binding startShiftActive}"/>
<Button Width="140" Content="Start Lunch" Command="{Binding startLunchCommand}"
IsEnabled="{Binding startLunchActive}"/>
<Button Width="140" Content="End Lunch" Command="{Binding endLunchCommand}"
IsEnabled="{Binding endLunchActive}"/>
<Button Width="140" Content="End Shift" Command="{Binding endShiftCommand}"
IsEnabled="{Binding endShiftActive}"/>
<Button Width="140" Content="Add Break" Command="{Binding addBreakCommand}"
IsEnabled="{Binding addBreakActive}"/>
</StackPanel>
<!--Right column text blocks-->
<StackPanel Grid.Column="1" Margin="10">
<TextBlock Text="{Binding day.timeIn, StringFormat=t, UpdateSourceTrigger=PropertyChanged, FallbackValue=StartTime}" FontSize="20"
Visibility="{Binding timeInValid, Converter={StaticResource BoolToVisConverter}}"
Padding="5" Margin="10"/>
<TextBlock Text="{Binding day.lunchStart, StringFormat=t, UpdateSourceTrigger=PropertyChanged, FallbackValue=LunchStart}" FontSize="20"
Visibility="{Binding lunchStartValid, Converter={StaticResource BoolToVisConverter}}"
Padding="5" Margin="10"/>
<TextBlock Text="{Binding day.lunchEnd, StringFormat=t, UpdateSourceTrigger=PropertyChanged}" FontSize="20"
Visibility="{Binding lunchEndValid, Converter={StaticResource BoolToVisConverter}, UpdateSourceTrigger=PropertyChanged}"
Padding="5" Margin="10"/>
<TextBlock Text="{Binding day.timeOut, StringFormat=t, UpdateSourceTrigger=PropertyChanged, FallbackValue=EndTime}" FontSize="20"
Visibility="{Binding timeOutValid, Converter={StaticResource BoolToVisConverter}, UpdateSourceTrigger=PropertyChanged}"
Padding="5" Margin="10"/>
</StackPanel>
</Grid>
BooleanToVisibilityConverter.cs
public class BooleanToVisiblityConverter : BaseValueConverter<BooleanToVisiblityConverter>
{
public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (parameter == null)
return (bool)value ? Visibility.Hidden : Visibility.Visible;
else
return (bool)value ? Visibility.Visible : Visibility.Hidden;
}
}
HomeViewModel.cs
private void startShift()
{
day.date = DateTime.Now;
dateValid = true;
day.timeIn = DateTime.Now;
timeInValid = true;
day.breaks = new ObservableCollection<Break>();
RaisePropertyChanged("day"); //A simple fix to update the UI
process(Command.startShift);
infoText = string.Format("Shift started at {0:t}", day.timeIn);
writeToFile();
}
private void startLunch()
{
day.lunchStart = DateTime.Now;
lunchStartValid = true;
RaisePropertyChanged("day");
process(Command.startLunch);
infoText = string.Format("Lunch started at {0:t}", day.lunchStart);
writeToFile();
}
private void endLunch()
{
day.lunchEnd= DateTime.Now;
lunchEndValid = true;
RaisePropertyChanged("day");
process(Command.endLunch);
infoText = string.Format("Lunch ended at {0:t}", day.lunchEnd);
writeToFile();
}
private void endShift()
{
day.timeOut = DateTime.Now;
timeOutValid = true;
RaisePropertyChanged("day");
calcTotalTime();
process(Command.endShift);
infoText = string.Format("Shift ended at {0:t}\nTotal time for {1:d} is {2}", day.timeOut, day.date, day.totalTime);
//Save to database
WorkHoursDBContext context = new WorkHoursDBContext();
context.Days.Add(day);
context.SaveChanges();
writeToFile();
}
The method process() is responsible for changing the boolean of each button to decide if it is enabled or not.
Is there any way I can prevent my End Shift TextBlock from sliding up when the Start Lunch and End Lunch TextBlocks are hidden?
I'm trying to dynamically bind a Flyout content to a view, like I would do to a TabControl, but when I load the view object the Flyout is empty. I tried loading the view directly below the Controls:FlyoutsControl and it worked, so I don't think the problem is with the view itself.
Also, I need to load this in a specific Flyout, so using the ItemSource property in the Controls:FlyoutsControl wouldn't work for me.
MainWindow.xml
<Controls:MetroWindow.Flyouts>
<Controls:FlyoutsControl>
<Controls:Flyout
Content="{Binding FlyTest, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
IsOpen="{Binding IsOpen, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Background="#91000000"/>
</Controls:FlyoutsControl>
</Controls:MetroWindow.Flyouts>
UserControl1.xml - The View to be loaded
<controls:Flyout
x:Class="TestApp.View.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
Position="Right"
MinWidth="380" MaxWidth="380"
Header="Manufacturer Data">
<Grid>
<TextBox
Text="Test Data"
Grid.Row="0" Grid.Column="0"
VerticalAlignment="Center"
HorizontalAlignment="Right"/>
</Grid>
</controls:Flyout>
MainWindowViewModel.cs
private UserControl1 _flyTest;
public UserControl1 FlyTest
{
get { return _flyTest; }
set
{
_flyTest = value;
RaisePropertyChanged("FlyTest");
}
}
private void LoadTabs()
{
FlyTest = new UserControl1();
IsOpen = true;
}
I figured it out by changing the view object type from Flyout to UserControl
I am creating custom phone book which reads phone book contacts and displays inside my application. So I am creating a long list selector and a listbox inside it.
My listbox will contain phone contact name and list of phone number with the check box under the particular name. I wrote an event trigger inside my listbox to make track of the checkbox is clicked or not.
PROBLEM : Event is not firing in the view model. I suspect since the listbox is present inside another list(long list selector), event is not firing.
Here is xaml code:
<phone:LongListSelector Grid.Row="3" LayoutMode="List" ItemsSource="{Binding PhoneBookDataSource}" IsGroupingEnabled="True" HideEmptyGroups="True">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical" >
<TextBlock Text="{Binding PhoneContactName}" FontWeight="SemiBold" FontSize="36" Foreground="Green"></TextBlock>
<ListBox ItemsSource="{Binding LstPhoneContactNumber,Mode=TwoWay}" ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Tap">
<i:InvokeCommandAction Command="{Binding PhoneNumberCheckedStateChangeCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Width="480">
<TextBlock Text="{Binding PhoneNumberItem}" FontSize="25" HorizontalAlignment="Left" VerticalAlignment="Center" Foreground="Gray"></TextBlock>
<CheckBox Foreground="Black" Background="Black" VerticalAlignment="Center" HorizontalAlignment="Right" IsChecked="{Binding IsPhoneNumberItemChecked,Mode=TwoWay}"></CheckBox>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
<phone:LongListSelector.GroupHeaderTemplate>
<DataTemplate>
<Border Background="Transparent" Padding="5">
<Border Background="{StaticResource PhoneAccentBrush}" BorderBrush="{StaticResource PhoneAccentBrush}" BorderThickness="2" Width="62"
Height="62" Margin="0,0,18,0" HorizontalAlignment="Left">
<TextBlock Text="{Binding Key}" Foreground="{StaticResource PhoneForegroundBrush}" FontSize="48" Padding="6"
FontFamily="{StaticResource PhoneFontFamilySemiLight}" HorizontalAlignment="Left" VerticalAlignment="Center"/>
</Border>
</Border>
</DataTemplate>
</phone:LongListSelector.GroupHeaderTemplate>
<phone:LongListSelector.JumpListStyle>
<Style TargetType="phone:LongListSelector">
<Setter Property="GridCellSize" Value="113,113"/>
<Setter Property="LayoutMode" Value="Grid" />
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<Border Background="{Binding Converter={StaticResource BackgroundConverter}}" Width="113" Height="113" Margin="6" >
<TextBlock Text="{Binding Key}" FontFamily="{StaticResource PhoneFontFamilySemiBold}" FontSize="48" Padding="6"
Foreground="{Binding Converter={StaticResource ForegroundConverter}}" VerticalAlignment="Center"/>
</Border>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</phone:LongListSelector.JumpListStyle>
</phone:LongListSelector>
Here is my view model:
public DelegateCommand PhoneNumberCheckedStateChangeCommand { get; set; }
public DelegateCommand SendSMSCommand { get; set; }
public CustomPhoneBookViewModel(INavigationService nav, IDataService data, IAESEnDecrypt encrypt, IGeoLocationService geoLocation, IMessageBus msgBus, ISmartDispatcher smartDispatcher)
: base(nav, data, encrypt, geoLocation, msgBus, smartDispatcher)
{
IsProgressBarBusy = true;
PhoneContactsList = new ObservableCollection<PhoneBookEntity>();
PhoneBookDataSource = new ObservableCollection<LLSAlphaKeyGroup<PhoneBookEntity>>();
InitializeDelegateCommands();
GetDeviceResolution();
ReadPhoneBook();
}
private void OnPhoneNumberItemCheckedStateChangedCommand()
{
try
{
foreach (var parentItem in PhoneBookDataSource)
{
foreach (var childItem in parentItem)
{
foreach (var item in childItem.LstPhoneContactNumber)
{
if (item.IsPhoneNumberItemChecked)
IsSendSMSButtonEnabled = true;
return;
}
}
IsSendSMSButtonEnabled = false;
}
}
catch { }
finally
{
SendSMSCommand.RaiseCanExecuteChanged();
}
}
Any suggestions is appreciated!!
The easiest way of making the nested ListBox interaction bind to the global ViewModel (instead of to its own, nested DataContext) is to assign a unique name to the outmost LongListSelector:
<phone:LongListSelector x:Name="OuterList" Grid.Row="3" LayoutMode="List" ItemsSource="{Binding PhoneBookDataSource}" IsGroupingEnabled="True" HideEmptyGroups="True">
and explicitly bind the Command to this element's DataContext (which is the global ViewModel):
<i:InvokeCommandAction Command="{Binding ElementName=OuterList, Path=DataContext.PhoneNumberCheckedStateChangeCommand}" />
I use an observableCollecion in my VM. This Collection is bind into my view in a ListView. In my items I try to get the element who create this item. Add it in my commandParameter and do the thing.
Here's my VM :
public RelayCommand<SelectionCommandParameter> CmdRemoveFromQuiz { get; set; }
public ObservableCollection<Question> SelectedQuiz
{
get { return _selectedQuiz; }
set
{
_selectedQuiz = value;
RaisePropertyChanged("SelectedQuiz");
}
}
private void RemoveFromQuiz(SelectionCommandParameter selection)
{
if (selection.Parameter is Question)
{
ObservableCollection<Question> tempQuiz = SelectedQuiz;
Question _question = (Question)selection.Parameter;
tempQuiz.Remove(_question);
SelectedQuiz = tempQuiz;
}
}
The problem start with the RemoveBtn I start the command, and selection stay null I want to get the ObservableCollection<Question> object use in my ListViewitem
Now My View :
<userControls:CharmFlyout
x:Name="cfoQuizList"
x:Uid="QuizListCreatingPageFlyout"
Heading="Question Multiple"
HorizontalAlignment="Left"
Grid.Column="0"
Grid.RowSpan="2"
Style="{StaticResource stlAddRecipientFlyout}">
<tut:TutorialAwareListView x:Name="gvQuizItem"
ItemsSource="{Binding SelectedQuiz}"
IsItemClickEnabled="True"
CanReorderItems="True"
SelectionMode="None"
ManipulationMode="TranslateRailsX">
<ListView.ItemTemplate>
<DataTemplate x:Name="DTQuizItem">
<Grid HorizontalAlignment="Left" Width="{StaticResource RectangleTileWidth}" Height="{StaticResource RectangleTileHeight}"
Margin="0 0 0 0" Background="{StaticResource OrangeBackgroundThemeBrush}">
<Grid Grid.Column="1">
<Button x:Name="RemoveBtn" Content="X" HorizontalAlignment="Right" VerticalAlignment="Top" Width="40" Height="40"
BorderThickness="0" Command="{Binding DataContext.CmdRemoveFromQuiz, ElementName=gvQuizItem}" CommandParameter="{Binding Question}"/>
<maxCtrls:MaxAutoScrollingContentPresenter VerticalAlignment="Center"
ScrollingDuration="{Binding Name, Converter={StaticResource TextToTimeToReadShortFormatConverter}}"
ScrollingBeginTime="0:0:2">
<TextBlock Text="{Binding Name}" FontWeight="SemiBold"
Foreground="{StaticResource WhiteBackground}"
Margin="20,5,10,5" VerticalAlignment="Center" TextWrapping="Wrap"/>
</maxCtrls:MaxAutoScrollingContentPresenter>
</Grid>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</tut:TutorialAwareListView>
</userControls:CharmFlyout>
The TutorialAwareListView Work exactly like a ListView. I use it juste to point the element while the tutorial is running.
It's a Windows Store App !! I can't do all the thing we would like to.
You should change your SelectionMode="None" to Single or Multiply.
And make new ObservableCollection for selected items. You bind just ItemsSource="{Binding SelectedQuiz}". Bind SelectedItems="{...}"
In a group of toggle switches I couldn't control the any toggle switch individually, rather if I try to change one then all the values change simultaneously.
My Xaml:-
<ListBox HorizontalAlignment="Left" ScrollViewer.VerticalScrollBarVisibility="Disabled" Margin="0,0,0,0" Name="yourChoiceListBox" VerticalAlignment="Top" Width="476" ItemsSource="{Binding yourChoiceList, Mode=TwoWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Gray" BorderThickness="1">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Center" Width="476" Height="60">
<TextBlock Margin="10,0,0,0" FontSize="24" FontWeight="SemiBold" Foreground="Black" Width="250" Text="{Binding title}" VerticalAlignment="Center" Height="35" TextTrimming="WordEllipsis" />
<TextBlock FontSize="24" FontWeight="SemiBold" Foreground="Black" Width="150" Text="{Binding valueDesc}" HorizontalAlignment="Right" FlowDirection="RightToLeft" VerticalAlignment="Center" Visibility="{Binding valueVisible}" />
<toolkit:ToggleSwitch x:Name="toggle" Foreground="Black" Content="{Binding toggleContent}" IsChecked="{Binding DataContext.isCheck,ElementName=yourChoiceListBox,Mode=TwoWay}" Height="110" Width="198" HorizontalAlignment="Right" Margin="40,-15,0,0" Visibility="{Binding tongleVisible}" />
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
My ViewModel CS:-
public static string _toggleContent;
public string toggleContent
{
get { return _toggleContent; }
set { this.RaiseAndSetIfChanged(x => x.toggleContent, value); }
}
public static bool _isCheck;
public bool isCheck
{
get { return _isCheck; }
set
{
this.RaiseAndSetIfChanged(x => x.isCheck, value);
if (isCheck)
toggleContent = "Yes";
else
toggleContent = "No";
}
}
Here i want to change the toggle switch content in to "Yes" or "No". If i choose 'On' the content should be "Yes". But here if i select one toggle switch all the toggle switch is changed. Please let me any idea to solve my problem. Thanks in advance.
This is your ToggleSwitch:
<toolkit:ToggleSwitch x:Name="toggle" Foreground="Black" Content="{Binding toggleContent}"
IsChecked="{Binding DataContext.isCheck,ElementName=yourChoiceListBox,Mode=TwoWay}"
Height="110" Width="198" HorizontalAlignment="Right" Margin="40,-15,0,0"
Visibility="{Binding tongleVisible}" />
the problem is here:
IsChecked="{Binding DataContext.isCheck,ElementName=yourChoiceListBox,Mode=TwoWay}"
You are binding the IsChecked property of the ToggleSwitch to the isCheck property of your list.
You should bind the IsChecked property of the ToggleSwitch to the isCheck property of your list item like this:
IsChecked="{Binding isCheck, Mode=TwoWay}"