Displayed image in UI locks the source file - c#

I have a DataTemplate which was created from here:
ComboBoxes sharing Observable Collection keeps breaking
<UserControl.Resources>
<DataTemplate x:Key="ImageItemTemplate">
<StackPanel Orientation="Horizontal">
<Image Height="44" Source="{Binding Path}"/>
<Label Content="{Binding Name}" VerticalAlignment="Center"/>
</StackPanel>
</DataTemplate>
</UserControl.Resources>
<ComboBox x:Name="image1" ItemTemplate="{StaticResource ImageItemTemplate}"/>
Code:
public ObservableCollection<ImageItem> images = new ObservableCollection<ImageItem>();
Generic.ImportGrfx(tabID, image1, images);
public static void ImportGrfx(string tabID, ComboBox combo, ObservableCollection<ImageItem> items)
{
items.Clear();
try
{
string root = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
var files = Directory.GetFiles(Path.Combine(root, "input\\" + tabID), "*.png");
foreach (var file in files)
{
ImageItem item = new ImageItem();
item.Path = file;
item.Name = Path.GetFileName(file).Remove(Path.GetFileName(file).Length - 4);
items.Add(item);
}
}
catch (Exception) { }
combo.ItemsSource = items;
}
public class ImageItem
{
public string Path { get; set; }
public string Name { get; set; }
}
The problem I am having is binding these images to the datatemplate, "locks" the image source. Meaning I can't edit the images while the program is running... I would get an error stating the image is in use. Is there a way to fix this?

Here's a skeleton of an Image that will get updated whenever you modify it from outside.
you set the source, it copies it to a temp path and loads the image from there
it watches for changes in initial image and updates itself again
rinse and repeat :D
You can, not use the auto-update feature if you only need the ability to edit the image from outside.
It's really basic so feel free to improve ...
Code:
using System;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
namespace WpfApplication4
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Loaded += MainWindow_Loaded;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
DynamicImage1.SetSource(#"d:\Untitled.png");
}
}
internal class DynamicImage : Image
{
private string _name;
private FileSystemWatcher _watcher;
public void SetSource(string fileName)
{
if (fileName == null) throw new ArgumentNullException("fileName");
if (_watcher != null)
{
_watcher.Changed -= watcher_Changed;
_watcher.Dispose();
}
string path = Path.GetDirectoryName(fileName);
_watcher = new FileSystemWatcher(path);
_watcher.EnableRaisingEvents = true;
_watcher.Changed += watcher_Changed;
_name = fileName;
string tempFileName = Path.GetTempFileName();
File.Copy(fileName, tempFileName, true);
Source = new BitmapImage(new Uri(tempFileName));
}
private void watcher_Changed(object sender, FileSystemEventArgs e)
{
bool b = string.Equals(e.FullPath, _name, StringComparison.InvariantCultureIgnoreCase);
if (b)
{
string tempFileName = Path.GetTempFileName();
File.Copy(e.FullPath, tempFileName, true);
Dispatcher.BeginInvoke((Action) (() => { Source = new BitmapImage(new Uri(tempFileName)); }));
_name = e.FullPath;
}
}
}
}
XAML:
<Window x:Class="WpfApplication4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wpfApplication4="clr-namespace:WpfApplication4"
Title="MainWindow" Height="350" Width="525">
<Grid>
<wpfApplication4:DynamicImage x:Name="DynamicImage1" />
</Grid>
</Window>

Related

Can't Binding Property in TextBox's Text

I coding WPF App with Mahapps.Metro.
At that time, I’m cording a process that will display a dialog asking the user to select a directory and then display that directory in a Textbox.
Wrote the code shown below and got it to work, but the selected directory was not display in the Textbox.
xaml source:
<mah:MetroWindow x:Class="LogAnalysisProto_2.ToolLancher"
...
d:DataContext="{d:DesignInstance {x:Type local:ToolLancherViewModel},IsDesignTimeCreatable=True}"
mc:Ignorable="d"
Title="Sample" Height="610" Width="970"
>
<Grid>
<StackPanel Orientation="Horizontal">
<Label Style="{DynamicResource CommonLabel}" Content="Target Folder"/>
<Button x:Name="targetFolderOpen" Style="{DynamicResource MahApps.Styles.Button.Flat}" HorizontalAlignment="Center" Width="100" Margin="50,0,0,0" BorderBrush="{x:Null}" Background="{x:Null}" Click="targetFolderButton_Click">
<iconPacks:PackIconModern Width="30" Height="20" Kind="Folder" VerticalAlignment="Center"/>
</Button>
<TextBox x:Name="targetFolderTextBox" Text="{Binding TargetFolderPath}" Style="{DynamicResource MahApps.Styles.TextBox}" Height="32" Width="660" VerticalAlignment="Center"></TextBox>
</StackPanel>
</Grid>
</mah:MetroWindow>
code behind:
public partial class ToolLancher : MetroWindow
{
public ToolLancher()
{
DataContext = new ToolLancherViewModel();
InitializeComponent();
}
private void targetFolderButton_Click(object sender, RoutedEventArgs e)
{
var vm = DataContext as ToolLancherViewModel;
vm.PickTargetFolder();
//targetFolderTextBox.Text = vm.TargetFolderPath;
}
}
In ViewModel source(in ToolLancherViewModel):
public class ToolLancherViewModel : BaseViewModel
{
...
private string m_TargetFolderPath { get; set; }
/// <summary>
/// TargetFolder Property
/// </summary>
public string TargetFolderPath
{
get { return m_TargetFolderPath; }
set
{
m_TargetFolderPath = value;
IsExistsTargetDirectory = Directory.Exists(value);
NotifyPropertyChanged(nameof(TargetFolderPath));
}
}
/// <summary>
/// Select dialog path
/// </summary>
public void PickTargetFolder()
{
var path = PickFolder("TargetFolderBrowse");
if (string.IsNullOrEmpty(path)) return;
TargetFolderPath = path;
IsExistsTargetDirectory = true;
NotifyPropertyChanged(nameof(TargetFolderPath));
NotifyPropertyChanged(nameof(IsExistsTargetDirectory));
}
public static string PickFolder(string dialogTitle = "")
{
using (var folderPicker = new CommonOpenFileDialog()
{
Title = dialogTitle == string.Empty ? "SelectFolder" : dialogTitle,
InitialDirectory = initialDirectory,
IsFolderPicker = true,
})
{
if (folderPicker.ShowDialog() != CommonFileDialogResult.Ok)
{
return string.Empty;
}
return folderPicker.FileName;
}
}
}
BaseViewModel
public class BaseViewModel
{
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
var e = new PropertyChangedEventArgs(propertyName);
PropertyChanged?.Invoke(this, e);
}
}
Selecting Directory
After the Directory Select
There is no error.
Also, the binding method is already coded by me in another source, which is similarly written and works as expected.
In addition, the directory will appear in the TextBox without problems when specified in the following way.
private void targetFolderButton_Click(object sender, RoutedEventArgs e)
{
var vm = DataContext as ToolLancherViewModel;
vm.PickTargetFolder();
// Uncomment out this line
targetFolderTextBox.Text = vm.TargetFolderPath;
}
Correctly displayed example

Populate Listview using mvvm

i would like to ask how to Populate listview using MVVM pattern i'm beginner in mvvm pattern, i learn more from doing things than reading. i've done this before using wpf but i use code behind.
I use Mvvm Light. What i want is browse the Location of the folder and then populate the listview with the files inside it
so far i already have a Browse folder
i have this code
public class OpenFileDialogVM : ViewModelBase
{
public static RelayCommand OpenCommand { get; set; }
private string _selectedPath;
public string SelectedPath
{
get { return _selectedPath; }
set
{
_selectedPath = value;
RaisePropertyChanged("SelectedPath");
}
}
private string _defaultPath;
public OpenFileDialogVM()
{
RegisterCommands();
}
public OpenFileDialogVM(string defaultPath)
{
_defaultPath = defaultPath;
RegisterCommands();
}
private void RegisterCommands()
{
OpenCommand = new RelayCommand(ExecuteOpenFileDialog);
}
private void ExecuteOpenFileDialog()
{
var dialog = new FolderBrowserDialog();
dialog.ShowDialog();
SelectedPath = dialog.SelectedPath;
}
}
and i have this code for user control
<UserControl x:Class="MvvmLight1.FolderDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:vm="clr-namespace:MvvmLight1"
xmlns:local="clr-namespace:MvvmLight1"
mc:Ignorable="d" d:DesignWidth="300" Height="186.916" >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="90*"/>
<RowDefinition Height="97*"/>
</Grid.RowDefinitions>
<Grid>
<TextBox Text="{Binding SelectedPath}" />
</Grid>
<Grid Grid.Row="1" >
<Button Command="vm:OpenFileDialogVM.OpenCommand" >Browse</Button>
</Grid>
</Grid>
</UserControl>
so far the browse is working. my question is how can i call this code. after the selection of folder so that i can populate my listview?
private void Call(string selectedpath)
{
try
{
var allFiles = Directory.GetFiles(selectedpath, "*", SearchOption.AllDirectories);
foreach (var item in allFiles)
{
System.Console.WriteLine(item);
//code for populating listview
}
}
catch (System.Exception ex)
{
System.Console.WriteLine(ex.StackTrace);
throw ex;
}
}
Thank you for time.
Make Files a public observable collection.
Raise the PropertyChanged event.
Set the window's datacontext to your viewmodel.
Bind to the viewmodel's property in xaml.
CS
using System;
using System.ComponentModel;
using System.IO;
using System.Windows;
using System.Windows.Input;
using System.Collections.ObjectModel;
namespace StackOverflow_PopulateListView
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new OpenFileDialogVM();
}
}
public class OpenFileDialogVM : ViewModelBase
{
public static RelayCommand OpenCommand { get; set; }
private string _selectedPath = "Enter a Path";
public string SelectedPath
{
get { return _selectedPath; }
set
{
_selectedPath = value;
OnPropertyChanged("SelectedPath");
}
}
private ObservableCollection<string> _files = new ObservableCollection<string>() { "Tits", "balls", "ass", "tits" };
public ObservableCollection<string> Files
{
get { return _files; }
set
{
_files = value;
OnPropertyChanged("Files");
}
}
private ICommand _selectFileCommand;
public ICommand SelectFileCommand
{
get
{
return _selectFileCommand ?? (_selectFileCommand = new RelayCommand(() => Call(SelectedPath)));
}
protected set
{
_selectFileCommand = value;
}
}
public void Call(string selectedpath)
{
try
{
Files = new ObservableCollection<string>(Directory.GetFiles(selectedpath, "*", SearchOption.AllDirectories));
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace);
throw ex;
}
}
}
public class RelayCommand : ICommand
{
public Action Act { get; set; }
/// <summary> Occurs when the target of the Command should reevaluate whether or not the Command can be executed. </summary>
public event EventHandler CanExecuteChanged;
public RelayCommand(Action act)
{
Act = act;
}
/// <summary> Returns a bool indicating if the Command can be exectued with the given parameter </summary>
public bool CanExecute(object obj)
{
return true;
}
/// <summary> Send a ICommand.CanExecuteChanged </summary>
public void ChangeCanExecute()
{
object sender = this;
EventArgs eventArgs = null;
CanExecuteChanged(sender, eventArgs);
}
/// <summary> Invokes the execute Action </summary>
public void Execute(object obj)
{
Act();
}
}
/// <summary>
/// Extremely generic ViewModelBase; for copy-pasting into almost any MVVM project
/// </summary>
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Fires PropertyChangedEventHandler, for bindables
/// </summary>
protected virtual void OnPropertyChanged(string name)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
}
XAML
<Window x:Class="StackOverflow_PopulateListView.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:StackOverflow_PopulateListView"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525"
>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="8*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<ListView ItemsSource="{Binding Files}" Grid.Row="0">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<TextBox Grid.Row="1"
Text="{Binding SelectedPath}"
/>
<Button Grid.Row="2"
Content="Call"
Command="{Binding SelectFileCommand}"
/>
</Grid>
</Window>
Your view model should have an ObservableCollection of file names
public ObservableCollection<string> FileNames { get; }
= new ObservableCollection<string>();
which is populated when a directory is selected:
var files = Directory.EnumerateFiles(selectedpath, "*", SearchOption.AllDirectories);
FileNames.Clear();
foreach (var file in files)
{
FileNames.Add(file);
}
You would then bind the ItemsSource property of a ListBox to that collection:
<ListBox ItemsSource="{Binding FileNames}"/>

How to load images to a page as soon as they are loaded from a folder in UWP

I'm using the AdaptiveGridView to load a list of images from a folder onto the page. my question is how can i load an image as soon as it's become ready and not have to wait for the entire list of images to be processed.
Here's my code:
C#
public class Images
{
public ImageSource ImageURL { get; set; }
public string ImageText { get; set; }
}
private List<Images> ImageCollection;
private async void Button_Click(object sender, RoutedEventArgs e)
{
ImageCollection = new List<Images>();
// pick a folder
var folderPicker = new Windows.Storage.Pickers.FolderPicker();
folderPicker.FileTypeFilter.Add(".jpg");
var folder = await folderPicker.PickSingleFolderAsync();
var filesList = await folder.CreateFileQueryWithOptions(new QueryOptions(CommonFileQuery.DefaultQuery, new string[] { ".jpg", ".png", ".jpeg" })).GetFilesAsync();
for (int i = 0; i < filesList.Count; i++)
{
StorageFile imagefile = filesList[i];
BitmapImage bitmapimage = new BitmapImage();
using (IRandomAccessStream stream = await imagefile.OpenAsync(FileAccessMode.Read))
{
bitmapimage.SetSource(stream);
}
ImageCollection.Add(new Images()
{
ImageURL = bitmapimage,
ImageText = filesList[i].Name
});
countPhotos.Text = i.ToString() + "out of" + filesList.Count.ToString();
}
AdaptiveGV.ItemsSource = ImageCollection;
}
XAML:
<Page.Resources>
<DataTemplate x:Key="PhotosList">
<Grid>
<Image Source="{Binding ImageURL}"
Stretch="UniformToFill"
HorizontalAlignment="Center"
VerticalAlignment="Center">
</Image>
</Grid>
</DataTemplate>
</Page.Resources>
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Button HorizontalAlignment="Left" VerticalAlignment="Top" Content="click me" Click="Button_Click">
</Button>
<TextBlock Name="countPhotos">
</TextBlock>
<ScrollViewer>
<UWPToolkit:AdaptiveGridView x:Name="AdaptiveGV"
ItemHeight="300" DesiredWidth="500"
ItemTemplate="{StaticResource PhotosList}">
</UWPToolkit:AdaptiveGridView>
</ScrollViewer>
</StackPanel>
I tired moving the AdaptiveGV.ItemsSource = ImageCollection; inside of the for loop but that slowed down the process and I dont think its the best way to accomplish what i'm trying to do here. any other suggestions?
Thanks
You should use an ObservableCollection instead of a List. You could then assign the collection to the ItemsSource property before adding the images. The ObservableCollection notifies the UI about changes, e.g. about added elements.
Besides that, you should also use the async BitmapImage.SetSourceAsync() method.
public class ImageItem
{
public ImageSource Image { get; set; }
public string ImageText { get; set; }
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
var imageCollection = new ObservableCollection<ImageItem>();
AdaptiveGV.ItemsSource = imageCollection;
for ...
{
...
await bitmapimage.SetSourceAsync(stream);
...
imageCollection.Add(new ImageItem()
{
Image = bitmapimage,
ImageText = filesList[i].Name
});
}
}
Note also that I've replaced the (confusing) names Images and ImageURL by
ImageItem and Image. You would have to change the Image.Source Binding in the DataTemplate to this:
<Image Source="{Binding Image}"
The next step could be to create a view model that holds the ObservableCollection<ImageItem> as a (read-only) property:
public class ViewModel
{
public ObservableCollection<ImageItem> ImageCollection { get; }
= new ObservableCollection<ImageItem>();
public async Task LoadImages(StorageFolder folder)
{
var queryOptions = new QueryOptions(
CommonFileQuery.DefaultQuery, new string[] { ".jpg", ".png", ".jpeg" });
var files = await folder.CreateFileQueryWithOptions(queryOptions).GetFilesAsync();
foreach (var file in files)
{
using (var stream = await file.OpenReadAsync())
{
BitmapImage image = new BitmapImage();
await image.SetSourceAsync(stream);
ImageCollection.Add(new ImageItem
{
Image = image,
ImageText = file.Name
});
}
}
}
}
You would assign the Page's DataContext to an instance of the view model in the Page constructor and call the LoadImages() method on Button Click:
public MainPage()
{
InitializeComponent();
DataContext = new ViewModel();
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
var folderPicker = new Windows.Storage.Pickers.FolderPicker();
folderPicker.FileTypeFilter.Add(".jpg");
var folder = await folderPicker.PickSingleFolderAsync();
if (folder != null)
{
await ((ViewModel)DataContext).LoadImages(folder);
}
}
In XAML, you would bind the ItemsSource property to the ImageCollection property like this:
<UWPToolkit:AdaptiveGridView ...
ItemsSource="{Binding ImageCollection}"
ItemTemplate="{StaticResource PhotosList}" />

How to send information from one window to another? WPF

How do I send information from one wpf window to another window. What I wanted is for string filepath to save the information it gets the first time it is called.
This is the problem, when I click button1 from window1.xmal.cs it calls openfile() from DocumentManager.cs. And when I access filepath from window2.xmal.cs it gives an empty string. I want to save the filepath string I got from when it was called from window1.xmal.cs.
Here is what I have:
window1.xmal.cs
DocumentManager mgr = new DocumentManager();
private void Button1_Click(object sender, RoutedEventArgs e) {
ImageSource imgsource = new BitmapImage(new Uri(mgr.openfile().ToString()));
themeImage.Source = imgsource;
}
DocumentManager.cs
public string filePath;
public object openfile() {
OpenFileDialog open = new OpenFileDialog();
bool? result = open.ShowDialog();
if (result == true) {
filePath = open.FileName;
}
return filePath;
}
I think your problem is the way you are instantiating the DocumentManager class.
I've made an example that works. Here's the code:
MainWindow
public partial class MainWindow : Window
{ DocumentManager mgr;
Window2 w2;
public MainWindow() { InitializeComponent(); }
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{ mgr = new DocumentManager(); w2 = new Window2(); w2.Show(); }
private void Button_Click(object sender, RoutedEventArgs e)
{ ImageSource imgsource; string imglocation;
try {
imglocation = mgr.openfile().ToString();
imgsource = new BitmapImage(new Uri(imglocation));
result.Text = imglocation;
w2.imgsource = imgsource;
}
catch (Exception ex)
{ System.Windows.MessageBox.Show(ex.Message); }
}
}
DocumentManager
class DocumentManager
{
public string filePath;
public string openfile()
{
Microsoft.Win32.OpenFileDialog open = new Microsoft.Win32.OpenFileDialog();
bool? result = open.ShowDialog();
if (result == true) { filePath = open.FileName; }
else { filePath = "Nothing Opened"; }
return filePath;
}
}
MainWindow XAML
<Window x:Class="CrossClassDialog.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="120" Width="350" Loaded="MainWindow_Loaded">
<Grid>
<Button Content="Button" HorizontalAlignment="Left" VerticalAlignment="Top" Click="Button_Click"/>
<TextBlock x:Name="result" HorizontalAlignment="Left" Text="TextBlock" VerticalAlignment="Top" Margin="0,30,0,0"/>
</Grid>
</Window>
Window2 XAML
<Window x:Class="CrossClassDialog.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window2" Height="300" Width="300">
<Grid>
<Viewbox HorizontalAlignment="Left" VerticalAlignment="Top">
<Image x:Name="OpenedImage" Source="{Binding ImageSource}" />
</Viewbox>
</Grid>
</Window>
Add this property in Window2
private ImageSource _imgsource;
public ImageSource imgsource
{
get { return _imgsource; }
set
{
_imgsource = value;
OpenedImage.Source = value;
}
}
By the way, I changed a few things like the type your openfile() method returns.

Image not displaying XAML

I created my own button that has Icon on the side and text on the other but the problem is the image is not displaying. did i miss something here? any help would be appreciated. TIA
This is the XAML of the control.
<UserControl x:Name="QButtonControl"
x:Class="CommonLayout.QButton"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:CommonLayout"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="36"
d:DesignWidth="145" MinWidth="145" MinHeight="36" Loaded="QButtonControl_Loaded">
<Grid PointerEntered="Grid_PointerEntered_1" PointerExited="Grid_PointerExited_1" MinWidth="145" MinHeight="36" Background="#FFDCD1D1">
<TextBlock x:Name="btnLabel" Height="20" Margin="36,8,4,8" TextWrapping="Wrap" Text="Text Here" VerticalAlignment="Center" FontSize="18.667" Width="105"/>
<Image x:Name="img" HorizontalAlignment="Left" Height="27" Margin="1,4,0,0" VerticalAlignment="Top" Width="29"/>
</Grid>
</UserControl>
This is code behind the control.
public sealed partial class QButton : UserControl
{
private ImageSource iconDefault;
private Brush hoverBrush = new SolidColorBrush(Color.FromArgb(255, 228, 228, 228));
public string Text
{
get
{
return btnLabel.Text;
}
set
{
btnLabel.Text = value;
}
}
public ImageSource Icon
{
get
{
return iconDefault;
}
set
{
iconDefault = value;
img.Source = value;
}
}
public Brush HoverBrush
{
get
{
return hoverBrush;
}
set
{
hoverBrush = value;
}
}
public QButton()
{
this.InitializeComponent();
}
private void Grid_PointerEntered_1(object sender, PointerRoutedEventArgs e)
{
btnLabel.Foreground = HoverBrush;
}
private void Grid_PointerExited_1(object sender, PointerRoutedEventArgs e)
{
btnLabel.Foreground = Foreground;
}
private void QButtonControl_Loaded(object sender, RoutedEventArgs e)
{
img.Source = iconDefault;
}
}
First of all, do not use a hard coded file path to the image.
Windows Store apps run in a sandbox, so you will not be able to get to any arbitrary file location when you deploy your app.
Second, you can't use backslashes in Image URI. The backslashes are the technical reason you are setting the error you are getting. But just changing to forward slashes in not the answer.
Access Image in XAML
If you add an image to your projects /Assets folder, you can use XAML like this to show it in QButton.
<local:QButton x:Name='qButton1'
Icon='/assets/jellyfish.jpg' />
In Code
To change the Icon in code.
public MainPage()
{
this.InitializeComponent();
this.Loaded += MainPage_Loaded;
}
private async void MainPage_Loaded(object sender, RoutedEventArgs e)
{
var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/shrimp.jpg"));
var fileStream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read);
var image = new BitmapImage();
image.SetSource(fileStream);
qButton1.Icon = image;
}
If you want the user to choose the Image from their computer at runtime, look at the File Pickers.
MSDN file pickers
Are you forgetting to set the Icon property?
This worked for me
<local:QButton Icon="C:\Users\Public\Pictures\Sample Pictures\Penguins.jpg" />
This worked as well
public QButton()
{
this.InitializeComponent();
Uri imageUri = new Uri(#"C:\Users\Public\Pictures\Sample Pictures\Penguins.jpg");
BitmapImage image = new BitmapImage(imageUri);
this.Icon = image;
}

Categories

Resources