Friends,
I am assigning the Background of RootFrame to application resources, It works when you explicitly write the Resource name like below
App.RootFrame.Background = (System.Windows.Media.ImageBrush)App.Current.Resources["Theme_6"];
but If I use below it doesn't work:
string themeName = "Theme_6";
App.RootFrame.Background = (System.Windows.Media.ImageBrush)App.Current.Resources[themeName];
Is it possible to use the 2nd options in wp8?
Thanks!
Panorama control (and I think Pivot controls as well) has some problem supporting late binding for background images.
When you hard-code the image paths, there is no problem displaying a static background image.
To assign background images 'on the fly' you should follow these steps;
Create a Property (MainBackGroundImage) within your associated
ViewModel, that implements INotifyPropertyChanged interface (if you
are using MVVM pattern you already have this infrastructure).
Assign any image path (this can be a remote URL as well) to this
property whenever you want to change the background image.
In your View hook up to your ViewModel's property changed event and
update the layout of the control where background image is going to
appear:
void viewModel_PropertyChanged(object sender,PropertyChangedEventArgs e)
{
if (e.PropertyName == “MainBackGroundImage”)
{
this.MainPanorama.UpdateLayout();
}
}
You might perhaps take a look at my open-source WP8 application where I did achieve dynamic background images.
Related
I have a UWP question about inheriting/ passing a event to a user control from the parent view to child.
I created a user control to display text overlays (see code below). We had a parent view that would display an overlay when the window is resized (see code below). The overlay would display the dimensions of the window when this even is triggered.
I moved the overlay to a user control and now I'm trying to pass that resized event to the overlay control. The hope is that we can register more events to the overlay control so it can display more then the resize
information. However, I'm not sure the best way to do this. My first idea was inheriting from the view, so i could just listen to the event from the overlay control, but that resulted in errors.
I believe due to the fact that the parent view has a ViewModel (i also created one for the overlay, not sure if its actually needed yet).
I have been reading about a lot of possible ways to do this, but I'm not sure which would be the best way to do this. Does anyone have any insight on this issue ? I would be open to suggestions, links, or just a general answer of
what is the best way to achieve this in our project.
Parent view
User Control
Parent Event
Control class
Some information i have been reading about:
https://documentation.devexpress.com/WPF/17449/MVVM-Framework/ViewModels/ViewModel-relationships-ISupportParentViewModel
https://learn.microsoft.com/en-us/dotnet/framework/wpf/advanced/preview-events
https://social.msdn.microsoft.com/Forums/windows/en-US/742077f6-e875-44d1-8bc4-6e6516db9eda/passing-the-parent-control-event-to-child-controls?forum=winforms
https://learn.microsoft.com/en-us/windows/uwp/xaml-platform/events-and-routed-events-overview
http://irisclasson.com/2013/12/10/passing-event-arguments-from-xaml-in-windows-store-apps-inputconverter-inputconverterparameter-etc/
https://learn.microsoft.com/en-us/windows/uwp/launch-resume/how-to-create-and-consume-an-app-service
Update
Adding the viewModel to the parent viewModel (terminal), and passing it to the control via the Datacontext did not work
As you're already using MVVM, I'd recommend going the full route utilizing "Interactivity", "Commands", and "child ViewModels". This is a commonly used patter in MVVM WPF applications, and can be applied to UWP apps as well.
Using "Interactivity" and interactions
The interactivity / behaviors library from Microsoft allows you to bind events in XAML to an ICommand in the ViewModel. You can get the managed NuGet package here.
From the official examples on GitHub, shortened:
<Button x:Name="button1" Content="Increment">
<Interactivity:Interaction.Behaviors>
<Interactions:EventTriggerBehavior EventName="Click" SourceObject="{Binding ElementName=button1}">
<Interactions:InvokeCommandAction Command="{Binding UpdateCountCommand}"/>
</Interactions:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
</Button>
Forward command data to child ViewModel
Having this event now routed to your command in your parent ViewModel, you can now either call your overlay ViewModel and pass the info directly to it:
private readony IOverlayViewModel _overlayViewModel;
public ICommand UpdateCountCommand { get; set; }
ctor(IOverlayViewModel overlayViewModel)
{
_overlayViewModel = overlayViewModel;
UpdatedCountCommand = new MyICommandImplementation(UpdatedCountCommand_Executed);
}
private void UpdatedCountCommand_Executed(/* Add correct method signature */)
{
// If needed, retrieve data from parameter...
// Update overlay ViewModel text
_overlayViewModel.Text = ""; // Whichever text was calculated before
}
Or you use a messenger (mediator pattern) to send it to an overlay.
I was misusing the bindings. x:Bind and Binding are using different types of context. For this binding to work we would need to set the parent's element Datacontext to 'this'. x:Bind on the other hand does this implicitly.
<views:OverlayView DataContext="{x:Bind ViewModel.Overlay}"></views:OverlayView>
How i can make this buttons with icons like these ??
Normally, in order to create stylized buttons in Winforms, you have to work with the Button.Image property:
this.myButton.FlatStyle = FlatStyle.Flat;
this.myButton.Image = // your image
// ...
The buttons in your image include a text, but since the enumeration System.Windows.Forms.TextImageRelation (used in the property Button.TextImageRelation) does not allow for a text below the image... obtaining the same style with this approach risks to become a hard task (using GDI, handling painting events, creating a derivative of the Button class, etc...), unless there is a trick that I don't know.
The fastest and simplest way to recreate the same style is to create a button with empty Text property and manually include the text in the image file. Actually, you set:
this.myButton.FlatStyle = FlatStyle.Flat;
this.myButton.ImageAlign = ContentAlignment.MiddleCenter;
this.myButton.Text = "";
and you put this image (just an example) straight into the control:
I am trying to detect changes in the Application.Resources Resource dictionary, so I can automatically change the Titlebar to the Accent Colour when it updates. All of the XAML controls and elements change automatically, and when setting a solid colour brush to the address of the DSDFS brush, its internal value changes.
This is the code I have tried to use to detect the change:
public static DependencyProperty accent = DependencyProperty.Register("DictChange", typeof(ResourceDictionary), typeof(Shell), new PropertyMetadata(Application.Current.Resources, new PropertyChangedCallback(accent_PropertyChanged)));
public ResourceDictionary DictChange
{
get { return (ResourceDictionary)GetValue(accent); }
set { SetValue(accent, value); }
}
private static void accent_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
_app.SetTitlebar();
}
I'm assuming its wrong though, or I'm not sure if that is the right thing to do to detect changes. There was a previous iteration where I used Application.Current.Resources["SystemControlBackgroundAccentBrush"] as SolidColorBrush and tried to detect its property, but that didn't work either.
What am I doing wrong? Please help :)
It might not be wrong, but it's probably not the best solution available.
In WinRT XAML, we have this new ThemeResource that updates the resources automatically. The tricky bit is to find a way to bind the ApplicationView.GetForCurrentView().TitleBar.BackgroundColor to SystemControlBackgroundAccentBrush.
In my answer to this question, I created a Behavior that attaches a custom TitleBar to the page. If you modify the Background property to something like this -
<local:FullScreenModeTitleBarBehavior Background="{ThemeResource SystemControlBackgroundAccentBrush}" />
Now run the app and you will see the background color gets updated when you change the accent color of the system, as shown in the picture below -
Basically in your case, you just need to create a similar (& simpler?) Behavior that acts like a bridge to link the BackgroundColor of the TitleBar to the SystemControlBackgroundAccentBrush, via ThemeResource binding.
Hope this helps!
I'm assuming its wrong though, or I'm not sure if that is the right thing to do to detect changes.
You cannot detect the key-value changes in the Resource Dictionary by registering a DependencyProperty because the ResourceDictionay is not an ObservableCollection Class.
There are no build-in support to detect the key-value changes in a Resource Dictionary.
As a workaround, you can consider create an internal observable collection to detect the changes.
I have an application that loads some objects and displays them in a grid. One of those objects is a preview image which could be either a local image file or an image file on a web location. Right now it is working but the performance isn't very good when scrolling because whenever a new item scrolls into view it has to load the preview which takes a second or two.
What I am trying to accomplish is that the box for the preview would show up and start loading the preview on a background thread when it is scrolled into view. When the image is loaded it would notify (via property change event in the view model) and the image would come into place. This way the UI remains responsive and the preview is just blank until it loads and then it shows up. I have the getter for the bound property starting the backgroundWorker if the image isn't already cached, and the worker routine is as follows (_previewCache is the backing property for the bound preview):
void bw_LoadPreview_DoWork(object sender, DoWorkEventArgs e)
{
BitmapImage _tempCache = new BitmapImage(new Uri(PreviewImagePath, UriKind.RelativeOrAbsolute));
if (_tempCache.CanFreeze)
{
_tempCache.Freeze();
Dispatcher.CurrentDispatcher.Invoke((Action)(delegate { _previewCache = _tempCache; }));
}
}
This seems to work pretty well on local files, though it takes a little longer than I would expect for the images to appear, but the UI remains responsive. However when the image is a web path, it always ends up as _tempCache.CanFreeze = false so it skips it and doesn't load. If I try to do the invoke without freezing, it says it can't use the object because it's owned by a different thread.
What am I missing? How do you load a web based image this way? Or is there a better way to approach this issue that I'm not seeing? Any help is greatly appreciated.
Right now I have a grid of six buttons, all with different images inside them. I have another set of six images, that are the original just with a gray tint to represent you selecting it. How do I change the image to the button to the new "selected image" when I select the button.
I am assuming you do it in the method:
private void button1_click(object sender, RoutedEventArgs e)
{
}
I'm having trouble figuring out what to put inside here. Normally I would think it would be something like:
button1.image = "image path";
However when making a WP7 application you cannot use the image keyword. Any advice on how to change the image of a button when clicked?
Write where you want to change the image
var brush = new ImageBrush();
brush.ImageSource = new BitmapImage(new Uri("/Images/YourImage.png",
UriKind.Relative));
btn.Background = brush;
In Silverlight (upon which the Windows Phone 7 framework is built) the Button control does not have an Image property. I presume that you have created your original buttons by placing an Image element as the child of the Button. On the assumption that you want the same behavior for a whole set of buttons, then it might make sense to use visual states instead. You coudl achieve a consistent look-and-feel by changing the opacity of the ContentPresenter, e.g. An Opacity of 0.75 for the "Normal" state and and Opacity of 1.0 for the "Selected" state.
Determing which button is the selected one would be the trickier part, but if you wrap your buttons in a ListBox then you can use the "Selected" visual state in the ItemContainerStyle.
If you want to continue with the approach that you've already taken, then given that you know that the content of the button is an Image, you could do something like the following:
private void button1_click(object sender, RoutedEventArgs e)
{
Button source = (Button)sender;
Image content = source.Content as Image;
if (null != content)
{
content.Source = new BitmapImage(new Uri("image path"));
}
}
In this approach you would, of course, also need to handle reverting the other buttons back to their "Normal" state, which the ListBox approach would handle for you.
What you're doing is a really good learning exercise - you'll learn lots about Silverlight by experimenting like this.
In addition to manually adjusting the image to match the button press state, I believe you can also achieve the effect you are looking for - that the button image becomes "gray" when pressed - you can do this using "Styles" and using "Behaviors". Take a look at posts like:
http://mstechno.wordpress.com/2009/08/28/silverlight-3-how-to-customize-a-button-with-expression-blend-3/
Windows Phone 7 (WP7) Change a button's background color on click
Some of the XAML in this might look daunting - and using Expression Blend takes some time to get used to - but you will get there. Good luck!