Textblock Text property not being set using OnLoaded event - c#

I Have a texblock on a specific page. I am navigation from a previous page where one a selection from a listbox is clicked, the object is stored the the APP.Xaml file as a property. On my navigating page, i call this object in the Loaded event for my listboxes and set their text property to their respective equivalents on my stored property from my App.xaml file.
The problem is, only one of 4 listboxes works while the other fail to show up. Anyone know why this may be. My code is below.
private void StopNameTextBlock_Loaded(object sender, RoutedEventArgs e)
{
StopNameTextBlock.Text = (Application.Current as App).SelectedBusStop.StopName;
}
private void BusDirectionTextBlock_Loaded(object sender, RoutedEventArgs e)
{
BusDirectionTextBlock.Text = "Towards: " + (Application.Current as App).SelectedBusStop.BusDirection;
}
private void BusesServedTextBlock_Loaded(object sender, RoutedEventArgs e)
{
BusesServedTextBlock.Text = "Buses Served: " + (Application.Current as App).SelectedBusStop.BusesServed;
}
From the code above. the first text block populates but the others do not. Help
Below is the XAML code.
<StackPanel Name="StopInfo" Orientation="Vertical" Margin="0,0,0,620">
<TextBlock Name="BusDirectionTextBlock" Loaded="BusDirectionTextBlock_Loaded" />
<TextBlock Name="BusesServedTextBlock" Loaded="BusesServedTextBlock_Loaded" />
<TextBlock Name="TimeRequestedTextBlock" />
</StackPanel>

Related

Access content in XAML from code behind without name

I'm new to C# and XAML, so please excuse any obvious mistakes.
Let's say I wanted to create 100 checkboxes, all with the same layout, and when you click the checkbox, it makes the text in a label that's a child to that checkbox turn bold. I don't want to write out 100 functions for 100 checkboxes, I want to make a single function each checkbox can call that'll do the same thing.
<CheckBox VerticalContentAlignment="Center" Checked="CheckBox_Checked">
<WrapPanel>
<Image> Width="50" Source="Images/example.jpg"/>
<Label VerticalContentAlignment="Center">Extra cheese</Label>
</WrapPanel>
</CheckBox>
I'm able to get the WrapPanel nested under the CheckBox, but I can't seem to do the same to get the Label which is nested in the WrapPanel.
private void CheckBox_Checked(object sender, RoutedEventArgs e)
{
CheckBox _cb = (CheckBox)sender;
WrapPanel _wp = (WrapPanel)(_cb).Content;
Label _lb = (Label)(_wp).Content;
_lb.FontWeight = FontWeights.Bold;
}
The wrap panel class doesn't have a content attribute. What you can use however is the Children attribute in a combination with FirstOrDefault OfType. the method could look somethind like this.
private void CheckBox_Checked(object sender, RoutedEventArgs e)
{
CheckBox _cb = (CheckBox)sender;
WrapPanel _wp = (WrapPanel)(_cb).Content;
Label lbl = _wp.Children.OfType<Label>().FirstOrDefault();
lbl.FontWeight = FontWeights.Bold;
}
You can easily access the element you want without the need for hierarchical transformations that exist in HTML and there is no need for different transformations, so we will have the following code:
File.xml
<CheckBox VerticalContentAlignment="Center" Checked="CheckBox_Checked" Unchecked="CheckBox_Checked">
<WrapPanel>
<Image Width="50" Source="Images/config.gif"/>
<Label VerticalContentAlignment="Center">Extra cheese</Label>
</WrapPanel>
</CheckBox>
File.cs
private void CheckBox_Checked(object sender, RoutedEventArgs e)
{
if (sender is CheckBox _cb)
{
if (_cb.FontWeight == FontWeights.Normal)
_cb.FontWeight = FontWeights.Bold;
else
_cb.FontWeight = FontWeights.Normal;
}
}

Why when saving to Settings radio button states it keep loading the first radio button state and not the last radio button state changed?

When loading :
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
radioButtonWatchDirectory.IsChecked = Properties.Settings.Default.RadioButtonWatchDirectory;
radioButtonWatchFile.IsChecked = Properties.Settings.Default.RadioButtonWatchFile;
checkBoxIncludeSubdirectories.IsChecked = Properties.Settings.Default.IncludeSubDirectories;
textBoxFileDirectory.Text = Properties.Settings.Default.BrowseFolderDialog;
}
When setting and saving :
private void radioButtonWatchFile_Checked(object sender, RoutedEventArgs e)
{
Properties.Settings.Default.RadioButtonWatchFile = (bool)radioButtonWatchFile.IsChecked;
Properties.Settings.Default.Save();
}
private void radioButtonWatchDirectory_Checked(object sender, RoutedEventArgs e)
{
Properties.Settings.Default.RadioButtonWatchDirectory = (bool)radioButtonWatchDirectory.IsChecked;
Properties.Settings.Default.Save();
}
When running the application once i checked true the Watch File radio button no matter if i check the Watch Directory radio button next time i will run the application the Watch File radio button will be checked. like it's not remembering changing it to the Watch Directory radio button.
The Include Subdirectories is working fine.
I tried this when loading :
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
radioButtonWatchDirectory.IsChecked = Properties.Settings.Default.RadiosTesting;
radioButtonWatchFile.IsChecked = Properties.Settings.Default.RadiosTesting;
checkBoxIncludeSubdirectories.IsChecked = Properties.Settings.Default.IncludeSubDirectories;
textBoxFileDirectory.Text = Properties.Settings.Default.BrowseFolderDialog;
}
When saving :
private void RadiosTests(object sender, RoutedEventArgs e)
{
if((bool)radioButtonWatchFile.IsChecked)
{
Properties.Settings.Default.RadiosTesting = (bool)radioButtonWatchFile.IsChecked;
Properties.Settings.Default.Save();
}
if((bool)radioButtonWatchDirectory.IsChecked)
{
Properties.Settings.Default.RadiosTesting = (bool)radioButtonWatchDirectory.IsChecked;
Properties.Settings.Default.Save();
}
}
but always the radioButtonWatchFile is checked when running the application again.
When a radio button is unchecked, the Checked event is not fired again. So, when you select another option, the setting of the previously checked option is not changed.
You could additionally subscribe to the Unchecked event of each radiobutton in order to manage the state in your settings object.
However, it might be a better idea to save some consolidated state of the currently selected option, instead of saving each radiobutton state individually.
Answer to why it always selects the file option: because both IsChecked properties are assigned true but only one can legally be selected, the selection of the first radiobutton is reset when the second one is initialized.
If you would revert the order of loading, the other button would be selected (this code is not a solution, just a demonstration of your error the other way around)
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
// reverse initialization order changes the outcome
radioButtonWatchFile.IsChecked = Properties.Settings.Default.RadiosTesting;
radioButtonWatchDirectory.IsChecked = Properties.Settings.Default.RadiosTesting;
// ...
}
€dit: example of managing the radiobutton state by name with a somewhat mvvm like approach.
Suppose you create a viewmodel for your mode selection:
// consider linking this viewmodel to your settings somehow
class ModeViewModel
{
public string SelectedMode { get; set; }
public bool WithSubdirectories { get; set; }
}
In your groupbox, listen to Checked events and establish a property to maintain your selected RadioButton state => Tag in this example. The checked event handler will be responsible for setting the Tag depending on the actual RadioButton selection. When a new selected RadioButton is assigned, the ModeViewModel is updated accordingly.
<GroupBox Name="ModeGroup" Header="Mode"
ToggleButton.Checked="RadioButtonChecked"
Tag="{Binding SelectedMode, Mode=OneWayToSource}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<RadioButton Name="WatchFile" Content="Watch File"/>
<RadioButton Name="WatchFolder" Content="Watch Directory"
Grid.Row="1" Grid.Column="0" HorizontalAlignment="Left"/>
<CheckBox Content="Include Subdirectories" IsChecked="{Binding WithSubdirectories}"
Grid.Row="1" Grid.Column="1" HorizontalAlignment="Right"/>
</Grid>
</GroupBox>
Checked event handler that maintains the Tag state depending on the selected RadioButton.Name
private void RadioButtonChecked(object sender, RoutedEventArgs e)
{
if (e.Source is RadioButton rb && sender is GroupBox gb)
gb.Tag = rb.Name;
}
Load the selected radiobutton state from a string, containing the name of a RadioButton.
// Initialize the datacontext with your ModeViewModel
public MainWindow()
{
InitializeComponent();
ModeGroup.DataContext = new ModeViewModel();
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
// Load from your settings instead
var selectedMode = nameof(WatchFolder);
if (!string.IsNullOrEmpty(selectedMode) &&
LogicalTreeHelper.FindLogicalNode(ModeGroup, selectedMode) is RadioButton checkedElement)
{
checkedElement.IsChecked = true;
}
}
If you tweak this example and actually use your settings as initialization source and backing store of your viewmodel, this should work for your scenario.
Working solution.
void radioButton_Checked(object sender, RoutedEventArgs e)
{
if ((bool)radioButtonWatchFile.IsChecked)
{
Properties.Settings.Default.RadioButtonWatchFile = true;
Properties.Settings.Default.RadioButtonWatchDirectory = false;
}
else
{
Properties.Settings.Default.RadioButtonWatchFile = false;
Properties.Settings.Default.RadioButtonWatchDirectory = true;
}
Properties.Settings.Default.Save();
}

ScrollIntoView property not working for gridview in windows 10 universal app

I tried this below code:
XAML Code:
<GridView x:Name="listgrid">
<GridView.ItemTemplate>
<DataTemplate>
<StackPanel Margin="15,15,0,0">
<Image Height="170" Width="170" Source="{Binding}"></Image>
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
Cs code:
for (int i = 1; i < 50; i++)
{
list.Add("ms-appx:///Images/A-aa.jpg");
}
listgrid.ItemsSource = list;
listgrid.ScrollIntoView(listgrid.Items[30]);
I above code to scroll view to my selected item, but it's not showing any changes, i think i used this property in a wrong way any one please help me to scroll to gridview position.
I have replied your same question in MSDN: https://social.msdn.microsoft.com/Forums/windowsapps/en-US/d0a772b3-80b9-4a11-92a9-89963c29a52f/scrollintoview-property-not-working-for-gridview-in-windows-10-universal-app?forum=wpdevelop
You need to have something more to distinguish items, for example, give every image a name since items you bind to GridView are same, ScrollIntoView default find the first one.
And commonly you need to set a height property for the GridView.
For more complex requirements, there is a good thread you can reference:
Windows 10 ScrollIntoView() is not scrolling to the items in the middle of a listview
Try to subscribe on Loaded event and call ScrollIntoView inside event handler:
listgrid.Loaded += Listgrid_Loaded;
....
private void Listgrid_Loaded(object sender, RoutedEventArgs e)
{
listgrid.ScrollIntoView(listgrid.Items[30]);
}
Try this
private void Gridview_Loaded(object sender, RoutedEventArgs e)
{
if (ShellPage.Current.SelectedRecItem != null)
{
this.gridview.SelectedItem = ShellPage.Current.SelectedRecItem;
this.gridview.UpdateLayout();
this.gridview.ScrollIntoView(ShellPage.Current.SelectedRecItem);
}
}

Entity Framework Context.Set<T>().Local would not sync with Datagrid after calling LoadAsync

Entity Framework Local property is an ObservableCollection and can be bind to lets say a datagrid. But its items do not update with call to LoadAsync, or do update actually but do not reflect into datagrid. Consider following example:
XAML
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<Button Content="Load" Click="btnLoad_Click"/>
<Button Content="LoadAsync" Click="btnLoadAsync_Click"/>
<Button Content="SetDataSource" Click="btnSetDataSource_Click"/>
</StackPanel>
<DataGrid Name="grdTest" Grid.Row="1"/>
</Grid>
Code Behind
TestContext db = new TestContext();
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
grdTest.ItemsSource = db.Suppliers.Local;
}
private void btnLoad_Click(object sender, RoutedEventArgs e)
{
var beforQuery = db.Suppliers.Local;
db.Suppliers.Load();
}
private void btnLoadAsync_Click(object sender, RoutedEventArgs e)
{
var beforQuery = db.Suppliers.Local;
db.Suppliers.LoadAsync();
}
private void btnSetDataSource_Click(object sender, RoutedEventArgs e)
{
grdTest.ItemsSource = null;
grdTest.ItemsSource = db.Suppliers.Local;
}
If I press Load button first, it behave as expected (load all items into collection and they are reflected into datagrid)
If I press LoadAsync button first, Only one item is loaded to Local items (which is another question, why only one item), but it is not reflected into datagrid, I can press SetDataSource to see that.
Each time I press LoadAsync only one item is added to the previous set!!
And If I press LoadAsync and then Load an error would come up and say "An ItemsControl is inconsistent with its items source"
Now my question is, how can I use LoadAsync and Local items properly?
If I can not load items form database with LoadAsync method, then what is its use?
The problem is that the ItemsSource is being updated on a different thread than the control's thread. If you're using .NET 4.5, you can use EnableCollectionSynchronization to allow multiple threads to access a collection.
See this answer for an example.

Win8 ComboBox IsDropDownOpen + Visibility causes Glitched UI

I am developing a Windows 8 App using XAML and C#.
I have a problem with my ComboBox, and have a simple example to demonstrate it.
Add the following to a Layout Aware Page (New BasicPage)
<ComboBox x:Name="comboBox1" DropDownClosed="comboBox1_DropDownClosed" Visibility="Collapsed" HorizontalAlignment="Left" Margin="179,217,0,0" Grid.Row="1" VerticalAlignment="Top" Width="998" Height="51">
<x:String>Option 1</x:String>
<x:String>Option 2</x:String>
<x:String>Option 3</x:String>
</ComboBox>
<Button Click="Button_Click" Margin="585,130,0,416" Grid.Row="1" Height="82" Width="154">
<Viewbox>
<TextBlock Text="Press Me" />
</Viewbox>
</Button>
Add this to the page's CodeBehind
private void Button_Click(object sender, RoutedEventArgs e)
{
comboBox1.Visibility = Windows.UI.Xaml.Visibility.Visible;
comboBox1.IsDropDownOpen = true;
}
private void comboBox1_DropDownClosed(object sender, object e)
{
comboBox1.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
}
Expected:
When the button is pressed, the ComboBox should appear and the options should expand, allowing the user to select one. Once the user has selected an option, the ComboBox disappears.
Actual Result:
When the button is pressed, nothing happens. If the button is pressed a second time, the ComboBox appears in a glitched state, and the app is essentially non-responsive. (All input is directed at the ComboBox, which never closes.
Note: The DropDownClosed event fires immediately after the Button_Click event does. Removing the event handler doesn't change anything, but it's interesting that the DropDownClosed event is firing.
Rejected Solution:
It was suggested to me to use Dispatcher.RunAsync to set IsDropDownOpen after the Visibility change has taken effect. This seems to be a race condition, because it only works some of the time. If there were a way to confirm that the ComboBox had been rendered visible, adding this check to the RunAsync method could solve the problem.
As a workaround, I'm currently delaying Dispatcher.RunAsync for 200 milliseconds, which is an annoying workaround. Any other ideas?
You're right, you need to make sure comboBox1 is actually rendered visible, before trying to set IsDropDownOpen. The way to do it is to make the second call via Dispatcher:
private void Button_Click(object sender, RoutedEventArgs e)
{
comboBox1.Visibility = Windows.UI.Xaml.Visibility.Visible;
Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => comboBox1.IsDropDownOpen = true);
}
What a nasty bug, ah?
A simple workaround is instead of using the Visibility property, use Opacity. It works as expected:
<ComboBox x:Name="comboBox1" DropDownClosed="comboBox1_DropDownClosed" Opacity="0" HorizontalAlignment="Left" Margin="179,217,0,0" Grid.Row="1" VerticalAlignment="Top" Width="998" Height="51">
<x:String>Option 1</x:String>
<x:String>Option 2</x:String>
<x:String>Option 3</x:String>
</ComboBox>
private void Button_Click(object sender, RoutedEventArgs e) {
comboBox1.Opacity = 1;
comboBox1.IsDropDownOpen = true;
}
private void comboBox1_DropDownClosed(object sender, object e) {
comboBox1.Opacity = 0;
}
Cheers!
I've tested the following on my desktop and Surface device, and it seems to work all the time. It is a variation on delaying setting IsDropDownOpen. I understand you may have tried some variation of this that produced a race condition. I am not seeing a race condtion, so hopefully it works for you as well.
// need this for Task
using System.Threading.Tasks;
...
// note async keyword added to function signature
async private void Button_Click(object sender, RoutedEventArgs e)
{
comboBox1.Visibility = Windows.UI.Xaml.Visibility.Visible;
// add small delay before opening dropdown
await Task.Delay(1);
comboBox1.IsDropDownOpen = true;
}

Categories