WP7/ XAML change image source on app start if theme is light - c#

my image is inside the datatemplate, what I want to do it is change the image if the wp theme is light
<DataTemplate x:Key="citiesItemTemplate">
<StackPanel Grid.Column="1" VerticalAlignment="Top">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Height="50" Tap="ProgLngGropus_Tap" Text="{Binding Name}" FontSize="26" Margin="12,-5,12,6"/>
<ToggleButton Grid.Column="2" x:Name="MyToggleButton" Style="{StaticResource FlipButton}">
<ToggleButton.Content>
<Image Grid.Column="2" Margin="0,-10,-33,0" Height="40" Width="40" x:Name="ArrowDownImg" Source="/Images/appbar.dark.arrow.down.circle.rest.png" />
</ToggleButton.Content>
</ToggleButton>
<TextBlock TextWrapping="Wrap" Text="{Binding Lang}" Grid.Column="0" Grid.Row="1" x:Name="Desc"
Foreground="Orange" Visibility="{Binding ElementName=MyToggleButton,
Path=IsChecked, Converter={StaticResource ValueConverterBoolToVis}}">
</TextBlock>
</Grid>
</StackPanel>
</DataTemplate>
But Im unable to access ArrowDownImg
Visibility darkBackgroundVisibility = (Visibility)Application.Current.Resources["PhoneDarkThemeVisibility"];
if (darkBackgroundVisibility != Visibility.Visible)
{
//Error in finding ArrowDownImg
***//ArrowDownImg.Source = "/Images/appbar.light.arrow.down.circle.rest.png"***
}

You could also do
Image arrowDownImg = MyObjectUsingTheDataTemplate.FindVisualChild("ArrowDownImg") as Image;
arrowDownImg.Source = ...
by using the following extension methods
public static FrameworkElement FindVisualChild(this FrameworkElement root, string name)
{
FrameworkElement temp = root.FindName(name) as FrameworkElement;
if (temp != null)
return temp;
foreach (FrameworkElement element in root.GetVisualDescendents())
{
temp = element.FindName(name) as FrameworkElement;
if (temp != null)
return temp;
}
return null;
}
public static IEnumerable<FrameworkElement> GetVisualDescendents(this FrameworkElement root)
{
Queue<IEnumerable<FrameworkElement>> toDo = new Queue<IEnumerable<FrameworkElement>>();
toDo.Enqueue(root.GetVisualChildren());
while (toDo.Count > 0)
{
IEnumerable<FrameworkElement> children = toDo.Dequeue();
foreach (FrameworkElement child in children)
{
yield return child;
toDo.Enqueue(child.GetVisualChildren());
}
}
}
public static IEnumerable<FrameworkElement> GetVisualChildren(this FrameworkElement root)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(root); i++)
{
yield return VisualTreeHelper.GetChild(root, i) as FrameworkElement;
}
}

Answer: Here is what I did
I have added the loaded event
<ToggleButton Grid.Row="0" Grid.Column="2" Margin="0,-10,-33,0" x:Name="MyToggleButton" Style="{StaticResource FlipButton}">
<ToggleButton.Content>
<Image Loaded="ArrowDownImg_Loaded" Height="50" Width="50" x:Name="ArrowDownImg" />
</ToggleButton.Content>
</ToggleButton>
and in the event:
private void ArrowDownImg_Loaded(object sender, RoutedEventArgs e)
{
Visibility darkBackgroundVisibility = (Visibility)Application.Current.Resources["PhoneDarkThemeVisibility"];
var ArrowDownImg = sender as Image;
if (darkBackgroundVisibility != Visibility.Visible)
{
ArrowDownImg.Source = new BitmapImage(new Uri("/Images/appbar.arrow.down.circle.dark.rest.png", UriKind.Relative));
}
else
{
ArrowDownImg.Source = new BitmapImage(new Uri("/Images/appbar.arrow.down.circle.light.rest.png", UriKind.Relative));
}
}

Related

NotifyProperty not triggering

I've got two buttons on the same page, one just below my gallery and one in a bottom navigation bar. Both commands trigger but the bottom one is broken. It never goes to my NOTIFYProperyChanged
<Label Grid.Row="0" Grid.Column="0" Text="IMAGES" XAlign="Start" YAlign="Center" Style="{StaticResource Labelfont}" TextColor="White"/>
<Grid x:Name="ImageGallerys">
<Grid.RowDefinitions>
<RowDefinition Height="*">
</RowDefinition>
<RowDefinition Height="128">
</RowDefinition>
<RowDefinition Height="Auto">
</RowDefinition>
</Grid.RowDefinitions>
<Image
Source="{Binding PreviewImage}" Grid.Row="0">
</Image>
<custom:ImageGallery ItemsSource="{Binding Images}" Grid.Row="1">
<custom:ImageGallery.ItemTemplate>
<DataTemplate>
<Image Source="{Binding Source}" Aspect="AspectFit">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Path=BindingContext.PreviewImageCommand, Source={x:Reference EditIssue}}" CommandParameter="{Binding ImageId}" />
</Image.GestureRecognizers>
</Image>
</DataTemplate>
</custom:ImageGallery.ItemTemplate>
</custom:ImageGallery>
<Button
Grid.Row="2" Text="Photo" Command="{Binding CameraCommand}">
</Button>
<Button
Grid.Row="2" Text="Pick" Command="{Binding PickCommand}">
</Button>
</Grid>
<!--Bottom Navigation Bar-->
<Grid Grid.Row="2">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<StackLayout x:Name="slButtons" Grid.ColumnSpan="3" Grid.Row="1" Orientation="Horizontal" HorizontalOptions="FillAndExpand" Spacing="5" BackgroundColor="White">
<StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand" BackgroundColor="#FBB040">
<Button
Grid.Row="2" Text="Pick" Command="{Binding PickCommand}">
</Button>
</StackLayout>
This is the method just before the NotifyProperty should be called.
public async Task ExecutePickCommand()
{
var file = await CrossMedia.Current.PickPhotoAsync();
if (file == null)
return;
byte[] imageAsBytes = null;
using (var memoryStream = new MemoryStream())
{
file.GetStream().CopyTo(memoryStream);
file.Dispose();
imageAsBytes = memoryStream.ToArray();
}
if (imageAsBytes.Length > 0)
{
var resizer = DependencyService.Get<IImageResize>();
imageAsBytes = resizer.ResizeImage(imageAsBytes, 1080, 1080);
var imageSource = ImageSource.FromStream(() => new MemoryStream(imageAsBytes));
_images.Add(new GalleryImage { Source = imageSource, OrgImage = imageAsBytes });
}
}
This is the Notifypropery part, it supposed to go into the method ItemSourceChange as it does with my first button, with the second button it just ends after.
public static readonly BindableProperty ItemsSourceProperty =
BindableProperty.Create<ImageGallery, IList>(
view => view.ItemsSource,
default(IList),
BindingMode.TwoWay,
propertyChanging: (bindableObject, oldValue, newValue) => {
((ImageGallery)bindableObject).ItemsSourceChanging();
},
propertyChanged: (bindableObject, oldValue, newValue) => {
((ImageGallery)bindableObject).ItemsSourceChanged(bindableObject, oldValue, newValue);
}
);
public IList ItemsSource
{
get
{
return (IList)GetValue(ItemsSourceProperty);
}
set
{
SetValue(ItemsSourceProperty, value);
}
}
void ItemsSourceChanging()
{
if (ItemsSource == null)
return;
}
void ItemsSourceChanged(BindableObject bindable, IList oldValue, IList newValue)
{
if (ItemsSource == null)
return;
var notifyCollection = newValue as INotifyCollectionChanged;
if (notifyCollection != null)
{
notifyCollection.CollectionChanged += (sender, args) => {
if (args.NewItems != null)
{
if (args.NewItems.Count > 0)
{
foreach (var newItem in args.NewItems)
{
var view = (View)ItemTemplate.CreateContent();
var bindableObject = view as BindableObject;
if (bindableObject != null)
bindableObject.BindingContext = newItem;
_imageStack.Children.Add(view);
}
}
}
else
{
_imageStack.Children.Clear();
foreach (var Item in ItemsSource)
{
var view = (View)ItemTemplate.CreateContent();
var bindableObject = view as BindableObject;
if (bindableObject != null)
bindableObject.BindingContext = Item;
_imageStack.Children.Add(view);
}
}
if (args.OldItems != null)
{
// not supported
}
};
I discovered if I did this, it finaly calls notifyproperty like in the upper button. But it crashes now due to nullreference error in this button, as it seems to create Another instance or something?
<custom:ImageGallery ItemsSource="{Binding Images}" Grid.Row="1" x:Name="ImageGalleryss">
<Button
Grid.Row="3" Text="Pick" Command="{Binding PickCommand}">
</Button>
</custom:ImageGallery>

Command is not working inside control of border in wpf

I am binding window DragMove event to the border control for moving the window. Propert is local:EnableDragHelper.EnableDrag="True" you can check design below.
<Border Grid.Row="0" BorderThickness="1" BorderBrush="Black" Background="#467EAF" Name="borderHeader" local:EnableDragHelper.EnableDrag="True">
<StackPanel Grid.Row="0" VerticalAlignment="Center">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="100"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Center" Content="{Binding InspectionHistoryModel.CurrentDateTime,Mode=TwoWay}" FontWeight="Bold" Foreground="White" FontSize="18" Margin="5,0,0,0"></Label>
<TextBlock Grid.Row="0" Grid.Column="1" HorizontalAlignment="Left" Name="popupTaregetextblock" Margin="10,0,0,0" VerticalAlignment="Center">
<Hyperlink FontSize="20" Foreground="White" Command="{Binding ShowHideHeaderPopupCommand}" CommandParameter="onDuty"><TextBlock Text="{Binding InspectionHistoryModel.HeaderDutyText, Mode=TwoWay}" VerticalAlignment="Center" FontWeight="Bold" FontSize="18" Foreground="White"> </TextBlock></Hyperlink>
</TextBlock>
</Grid>
</StackPanel>
</Border>
Comamnd of Hyperlink (which put in inside of the border) is not working. How to possible this? Drag Code is
private static void UIElementOnMouseMove(object sender, MouseEventArgs mouseEventArgs)
{
var uiElement = sender as UIElement;
if (uiElement != null)
{
if (mouseEventArgs.LeftButton == MouseButtonState.Pressed)
{
DependencyObject parent = uiElement;
int avoidInfiniteLoop = 0;
// Search up the visual tree to find the first parent window.
while ((parent is Window) == false)
{
parent = VisualTreeHelper.GetParent(parent);
avoidInfiniteLoop++;
if (avoidInfiniteLoop == 1000)
{
// Something is wrong - we could not find the parent window.
return;
}
}
var window = parent as Window;
if (window.WindowState == WindowState.Maximized)
{
var mouseX = mouseEventArgs.GetPosition(window).X;
var width = window.RestoreBounds.Width;
var x = mouseX - width / 2;
if (x < 0)
{
x = 0;
}
else
if (x + width > SystemParameters.PrimaryScreenWidth)
{
x = SystemParameters.PrimaryScreenWidth - width;
}
window.WindowState = WindowState.Normal;
window.Left = x;
window.Top = 0;
// window.Width = window.ActualWidth;
// window.Height = window.ActualHeight;
// window.Left = 0;
// window.Top = 0;
// window.WindowStartupLocation = WindowStartupLocation.Manual;
// window.WindowState = WindowState.Normal;
}
window.DragMove();
}
}
}

Generating items in ListVIew

I need to generate a listview with data I have in an array
my XAML is:
<Page.Resources>
<DataTemplate x:Key="IconTextDataTemplate">
<StackPanel Orientation="Horizontal" Width="220" Height="60">
<Border Background="#66727272" Width="40" Height="40" Margin="10">
<Image Source="/SampleImage.png" Height="32" Width="32" Stretch="UniformToFill"/>
</Border>
<StackPanel Orientation="Vertical" VerticalAlignment="Center">
<TextBlock x:Name="Name" Margin="10,0,0,0" Width="170" Height="20" TextTrimming="WordEllipsis" Loaded="Name_Loaded"/>
<TextBlock x:Name="Description" Margin="10,0,0,0" Width="170" Height="20" TextTrimming="WordEllipsis" Loaded="Description_Loaded"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</Page.Resources>
<ListView x:Name="IconTextGrid" Height="400" ItemTemplate="{StaticResource IconTextDataTemplate}" Grid.Row="4" Margin="40,40,40,10" HorizontalAlignment="Stretch">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid MaximumRowsOrColumns="8"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
And the C# code:
private async void SearchBox_QuerySubmitted(SearchBox sender, SearchBoxQuerySubmittedEventArgs args)
{
foreach (var item in results)
{
IconTextGrid.Items.Add("");
nameStr = item.FirstName + " " + item.LastName;
descriptionStr = item.Email;
}
}
public T FindElementByName<T>(DependencyObject element, string sChildName) where T : FrameworkElement
{
T childElement = null;
var nChildCount = VisualTreeHelper.GetChildrenCount(element);
for (int i = 0; i < nChildCount; i++)
{
FrameworkElement child = VisualTreeHelper.GetChild(element, i) as FrameworkElement;
if (child == null)
continue;
if (child is T && child.Name.Equals(sChildName))
{
childElement = (T)child;
break;
}
childElement = FindElementByName<T>(child, sChildName);
if (childElement != null)
break;
}
return childElement;
}
private void Name_Loaded(object sender, RoutedEventArgs e)
{
TextBlock Name = FindElementByName<TextBlock>(this, "Name");
Name.Text = nameStr;
}
private void Description_Loaded(object sender, RoutedEventArgs e)
{
TextBlock Description = FindElementByName<TextBlock>(this, "Description");
Description.Text = descriptionStr;
}
This code should generate a list view with some items (in the array size) and put in every item the data from the cell in the array.
The problem is that only in one item I see the data from the array and in the other items there is nothing.
Wish for help, thanks
Your code is failing for at least one reason:
foreach (var item in results)
{
IconTextGrid.Items.Add("");
nameStr = item.FirstName + " " + item.LastName;
descriptionStr = item.Email;
}
you appear to be storing nameStr and descriptionStr into fields. But you are only storing the last item in results.
The good news is you can simplify and fix your code all at once. Using
foreach (var item in results)
{
var nameStr = item.FirstName + " " + item.LastName;
var descriptionStr = item.Email;
IconTextGrid.Items.Add(new { Name = nameStr, Description = descriptionStr });
}
That will create anonymous types with Name and Description properties for the ListView elements. You can then use:
<DataTemplate x:Key="IconTextDataTemplate">
<StackPanel ...>
<Image .../>
</Border>
<StackPanel ...>
<TextBlock Text="{Binding Name}" Margin="10,0,0,0" Width="170" Height="20" TextTrimming="WordEllipsis"/>
<TextBlock Text="{Binding Description} Margin="10,0,0,0" Width="170" Height="20" TextTrimming="WordEllipsis"/>
</StackPanel>
</StackPanel>
</DataTemplate>
And remove your FindElementByName, Name_Loaded, and Description_Loaded methods.

how to access elements in a StackPanel in listbox

I have a ListBox that contains a StackPanel which contains an Image and a TextBlock. I want to access the TextBlock via c# (code-behind) to change it's font manually.
Relevent XAML:
<ListBox x:Name="CategoriesListBox" Margin="0,0,-12,0" ItemsSource="{Binding Categories}" SelectionChanged="CategoriesListBox_SelectionChanged" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,17" Width="432" Height="62">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image x:Name="catImage" Source="{Binding icon}"/>
<TextBlock x:Name="catName" Grid.Column="1" Text="{Binding name_shown}" TextWrapping="Wrap" Style="{StaticResource PhoneTextLargeStyle}"/>
</Grid>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I need to access the "catName" TextBlock for all cells.
try this--->
private T FindFirstElementInVisualTree<T>(DependencyObject parentElement) where T : DependencyObject
{
var count = VisualTreeHelper.GetChildrenCount(parentElement);
if (count == 0)
return null;
for (int i = 0; i < count; i++)
{
var child = VisualTreeHelper.GetChild(parentElement, i);
if (child != null && child is T)
{
return (T)child;
}
else
{
var result = FindFirstElementInVisualTree<T>(child);
if (result != null)
return result;
}
}
return null;
}
u can use above method in this way--->
ListBoxItem item = this.list.ItemContainerGenerator.ContainerFromIndex(2) as ListBoxItem;
TextBlock txt = FindFirstElementInVisualTree<TextBlock>(item);
txt.Text = "some text";

Find control inside Listbox.ItemTemplate (WPF C#)

I have some problems finding the right TextBlock control inside a StackPanel.
My markup:
<ListBox Name="lstTimeline" ItemContainerStyle="{StaticResource TwItemStyle}"
MouseDoubleClick="lstTimeline_MouseDoubleClick">
<ListBox.ItemTemplate>
<DataTemplate>
<DockPanel MaxWidth="{Binding ElementName=lstTimeline, Path=ActualWidth}">
<Border Margin="10" DockPanel.Dock="Left" BorderBrush="White"
BorderThickness="1" Height="48" Width="48" HorizontalAlignment="Center">
<Image Source="{Binding ThumbNail, IsAsync=True}" Height="48" Width="48" />
</Border>
<StackPanel Name="stkPanel" Margin="10" DockPanel.Dock="Right">
<TextBlock Text="{Binding UserName}" FontWeight="Bold" FontSize="18" />
<TextBlock Text="{Binding Text}" Margin="0,4,0,0" FontSize="14"
Foreground="#c6de96" TextWrapping="WrapWithOverflow" />
<TextBlock Text="{Binding ApproximateTime}" FontSize="14"
FontFamily="Georgia" FontStyle="Italic" Foreground="#BBB" />
<TextBlock Text="{Binding ScreenName}" Name="lblScreenName" FontSize="14"
FontFamily="Georgia" FontStyle="Italic" Foreground="#BBB"
Loaded="lblScreenName_Loaded" />
</StackPanel>
</DockPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
My double click code:
private void lstTimeline_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
ListBoxItem lbi = (lstTimeline.SelectedItem as ListBoxItem);
StackPanel item = lbi.FindName("stkPanel") as StackPanel;
if (item != null)
MessageBox.Show("StackPanel null");
TextBlock textBox = item.FindName("lblScreenName") as TextBlock;
if (textBox != null)
MessageBox.Show("TextBlock null");
MessageBox.Show(textBox.Text);
}
But the StackPanel is null. How do find the right TextBlock in SelectedItem?
Thanks for your help.
ListBoxItem myListBoxItem = (ListBoxItem)(lstUniqueIds.ItemContainerGenerator.ContainerFromIndex(lstUniqueIds.SelectedIndex));
ContentPresenter myContentPresenter = FindVisualChild<ContentPresenter>(myListBoxItem);
DataTemplate myDataTemplate = myContentPresenter.ContentTemplate;
CheckBox target = (CheckBox)myDataTemplate.FindName("chkUniqueId", myContentPresenter);
if (target.IsChecked)
{
target.IsChecked = false;
}
else
{
target.IsChecked = true;
}
Function FindVisualChild can be found on the MSDN page FrameworkTemplate.FindName Method:
private childItem FindVisualChild<childItem>(DependencyObject obj)
where childItem : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
if (child != null && child is childItem)
return (childItem)child;
else
{
childItem childOfChild = FindVisualChild<childItem>(child);
if (childOfChild != null)
return childOfChild;
}
}
return null;
}
There's a specific function to use when you're looking for something whose name is defined in a template. Try it like this:
private void lstTimeline_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
ListBoxItem lbi = (lstTimeline.SelectedItem as ListBoxItem);
StackPanel item = Template.FindName("stkPanel",lbi) as StackPanel;
if (item != null)
MessageBox.Show("StackPanel null");
TextBlock textBox = Template.FindName("lblScreenName",item) as TextBlock;
if (textBox != null)
MessageBox.Show("TextBlock null");
MessageBox.Show(textBox.Text);
}
Linq to xml with a get and set model.
var item = ...
lstTimeline.SelectedIndex = -1;
lstTimeline.ItemsSource = item;

Categories