Getting image file path from PreviewMouseDown event (WPF/C#) - c#

I'm making an image viewer. I have a mouse event that is supposed to trigger when an image (or child of StackPanel in this case), is clicked. The event is triggered as intended. The problem is, since the pathfile of the images is different depending on whichever is selected (in which directory, etc.), I just don't know how to get the pathfile of the specific image that is currently clicked on. The directory depends on whichever folder is loaded, so the pathfile could be different everytime.
If you scroll all the way down to Image_Load(), I have the Pic.Fill which is a reference to the rectangle that is being filled with the image. I'm trying to find the first parameter for Uri(_,_), which is supposed to be where the #"path" of the current image is.
using System;
using System.IO;
using Microsoft.Win32;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Drawing;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Forms;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApp1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
FolderBrowserDialog fbd = new FolderBrowserDialog();
List<string> paths = new List<string>();
string[] extension = new[] { ".jpg", ".png", ".jpeg", ".gif", ".bmp", ".tif", ".tiff" };
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e) {
if (fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
string[] files = Directory.GetFiles(fbd.SelectedPath);
FileLocation.Text = fbd.SelectedPath;
}
}
private void OpenButton_Click(object sender, RoutedEventArgs e)
{
LoadPhotos();
}
private void LoadPhotos()
{
try
{
DirectoryInfo di = new DirectoryInfo(fbd.SelectedPath);
foreach (var fi in di.GetFiles().Where(f => extension.Contains(f.Extension.ToLower())).ToArray())
{
paths.Add(fi.FullName);
}
Photos.ItemsSource = paths;
} catch (Exception e)
{
Console.WriteLine("File not found.", e.Source);
}
}
private void Image_Load(object sender, MouseButtonEventArgs e)
{
// What is the reference here?
Pic.Fill = new ImageBrush { ImageSource = new BitmapImage(new Uri(/*Insert pathfile here*/, UriKind.Absolute)) };
}
}
}
Here's my .xaml. I've analyzed it to see a reference but the only thing that stands out is the Image Source, which I've tagged with a comment. It's set to { Binding . } which I'm going to assume means, whatever image is referenced. But how do I connect that variable reference to my Image_Load()? (which is declared on the instantiation of ListBox)
<Window x:Class="WpfApp1.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:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="1081" Width="1720.5">
<Grid Margin="0,0,2,-0.578">
<Button x:Name="OpenButton" Content="Load" HorizontalAlignment="Left" Height="44" Margin="1166.374,932.042,0,0" VerticalAlignment="Top" Width="145.666" Background="#FFDDDDDD" FontSize="24" Click="OpenButton_Click"/>
<Button x:Name="BrowseButton" Content="Browse" HorizontalAlignment="Left" Height="44" Margin="58.666,932.042,0,0" VerticalAlignment="Top" Width="134.166" Background="#FFDDDDDD" FontSize="24" Click="Button_Click"/>
<Rectangle x:Name="Pic" Fill="#FFF4F4F5" HorizontalAlignment="Left" Height="878.767" Margin="58.666,34.733,0,0" Stroke="Black" VerticalAlignment="Top" Width="1253.374"/>
<ScrollViewer VerticalScrollBarVisibility="Visible" Width="327.46" HorizontalAlignment="Left" Margin="1339.04,34.733,0,137.078" RenderTransformOrigin="0.5,0.5" >
<StackPanel Width="327.46" RenderTransformOrigin="0.516,0.496" HorizontalAlignment="Left" VerticalAlignment="Center" Height="878.085">
<ListBox x:Name="Photos"
Grid.Row="2" Grid.Column="1" Height="876" PreviewMouseDown="Image_Load">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Width="300" Height="100">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
/* Image Source? */
<Image Source="{Binding .}" Grid.Column="0"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</ScrollViewer>
<TextBlock x:Name="FileLocation" HorizontalAlignment="Left" Height="44" Margin="192.832,948.542,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="973.542" Foreground="#FF515151" TextAlignment="Center" FontSize="14"/>
</Grid>
</Window>
I've been learning on the way using Blend-- some youtube tutorials here and there. I've tried to look for a solution online but all the questions about it usually involve a static and specific directory. This is my first program and the only thing I need is that darn path file reference. There are so many object reference so I just don't even know how to wrap my head around it, being so unfamiliar with these classes. Some assistance would be very much appreciated! :)

Related

C# WPF Binding String to Textblock [duplicate]

This question already has answers here:
Why does WPF support binding to properties of an object, but not fields?
(2 answers)
Closed last month.
I am still a beginner and I'm trying to make a application where a user gets to choose a file. For that I use OpenFileDialog, which has worked fine for me in the past. The file path and content should then be each displayed in a separate textbox. I tried to achieve this by storing the content and path in two strings. Because I want to use those strings later on in my project in another .cs file I figured I make them globally accessable by defining them as public string content = "No file selected yet;. The "No file selected yet" should be the default text before the user has selected anything.
I searched online and tried to accomplish my goals by using DataContext and Binding, but I can't figure out how to make it work. This is the code I have right now:
xaml file:
<UserControl x:Class="Project_Neon.MVVM.View.ChooseFileView"
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:local="clr-namespace:Project_Neon.MVVM.View"
mc:Ignorable="d"
d:DesignHeight="423.4"
d:DesignWidth="548.4">
<StackPanel Background="White">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="70"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="70"/>
<RowDefinition Height="100"/>
<RowDefinition Height="35"/>
<RowDefinition Height="218.4"/>
</Grid.RowDefinitions>
<TextBlock Grid.Column="1"
Grid.ColumnSpan="2"
Margin="0,5,20,0"
Text="Choose File"
Foreground="Black"
FontSize="28"
FontFamily="/Fonts/#Kanit Semi"/>
<TextBlock Text="Select the text document with the cheat sheet.
Only Documents in a .txt format can be accepted."
Foreground="Black"
FontSize="22"
FontFamily="/Fonts/#Kanit Light"
Grid.Row="1"
Grid.Column="1"
Grid.ColumnSpan="2"
Margin="0,0,20,10"/>
<Button Grid.Row="2"
Grid.Column="1"
VerticalAlignment="Top"
Content="Select file"
Height="25"
Width="70"
FontFamily="/Fonts/#Kanit"
FontSize="14"
Style="{StaticResource SelectFileButtonTheme}"
Click="SelectFileButton_Click"/>
<Grid Grid.Row="2"
Grid.Column="2"
Height="25"
VerticalAlignment="Top"
Margin="0,0,20,0">
<Border Padding="10"
BorderBrush="#1f1f1f"
BorderThickness="1">
</Border>
<TextBlock Name="FilePathDisplay"
Text="{Binding Path=CheatFilePath}"
VerticalAlignment="Center"
Margin="5,0,0,0"
FontSize="14"
FontFamily="/Fonts/#Kanit Light"/>
</Grid>
<Grid Grid.Row="3"
Grid.Column="1"
Grid.ColumnSpan="2"
Margin="0,0,20,20">
<TextBlock Height="20"
VerticalAlignment="Top"
Background="#1f1f1f"
Foreground="White"
Text=" Preview:"
FontSize="14"
FontFamily="/Fonts/#Kanit"/>
<Border Padding="10"
BorderBrush="#1f1f1f"
BorderThickness="1"
Margin="0,20,0,0">
<ScrollViewer HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto" Margin="-10,-10,-10,-10">
<TextBlock Width="Auto"
TextWrapping="Wrap"
Text="{Binding Path=CheatFileContent}"
VerticalAlignment="Top"
FontSize="13"
Margin="1.5,0,1.5,0"
FontFamily="/Fonts/#Kanit Light"/>
</ScrollViewer>
</Border>
</Grid>
</Grid>
</StackPanel>
</UserControl>
and the xaml.cs:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Project_Neon.MVVM.View
{
/// <summary>
/// Interaction logic for ChooseFileView.xaml
/// </summary>
public partial class ChooseFileView : System.Windows.Controls.UserControl
{
public ChooseFileView()
{
InitializeComponent();
this.DataContext = this;
}
public string CheatFileContent = "No file selected yet";
public string CheatFilePath = "No file selected yet";
private void SelectFileButton_Click(object sender, RoutedEventArgs e)
{
using (OpenFileDialog openFileDialog = new OpenFileDialog())
{
openFileDialog.InitialDirectory = "c:\\";
openFileDialog.Filter = ".txt (*.txt)|*.txt";
openFileDialog.FilterIndex = 1;
openFileDialog.Multiselect = false;
openFileDialog.RestoreDirectory = true;
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
var CheatFileStream = openFileDialog.OpenFile();
using (StreamReader reader = new StreamReader(CheatFileStream))
{
CheatFileContent = reader.ReadToEnd();
CheatFilePath = openFileDialog.FileName;
OnPropertyChanged(nameof(CheatFilePath));
OnPropertyChanged(nameof(CheatFileContent));
}
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
I'm afraid that maybe my strings aren't defined right.
(I deleted most of the code from my previous attempts of actually binding the data, because I only got errors.)
As #Andy pointed out you need to bind to properties not fields (check #Marc Gravell answer)
I included the raising of the event inside the setter as it makes more sense
ChooseFileView.xaml.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Project_Neon.MVVM.View
{
/// <summary>
/// Interaction logic for ChooseFileView.xaml
/// </summary>
public partial class ChooseFileView : System.Windows.Controls.UserControl, System.ComponentModel.INotifyPropertyChanged
{
private string _cheatFileContent;
private string _cheatFilePath;
public event PropertyChangedEventHandler? PropertyChanged;
public string CheatFileContent
{
get => _cheatFileContent;
set
{
if (_cheatFileContent != value)
{
_cheatFileContent = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CheatFileContent)));
}
}
}
public string CheatFilePath
{
get => _cheatFilePath;
set
{
if (_cheatFilePath != value)
{
_cheatFilePath = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CheatFilePath)));
}
}
}
public ChooseFileView()
{
InitializeComponent();
this.DataContext = this;
CheatFileContent = "No file selected yet";
CheatFilePath = "No file selected yet";
}
private void SelectFileButton_Click(object sender, RoutedEventArgs e)
{
using (OpenFileDialog openFileDialog = new OpenFileDialog())
{
openFileDialog.InitialDirectory = "c:\\";
openFileDialog.Filter = ".txt (*.txt)|*.txt";
openFileDialog.FilterIndex = 1;
openFileDialog.Multiselect = false;
openFileDialog.RestoreDirectory = true;
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
var CheatFileStream = openFileDialog.OpenFile();
using (StreamReader reader = new StreamReader(CheatFileStream))
{
CheatFileContent = reader.ReadToEnd();
CheatFilePath = openFileDialog.FileName;
}
}
}
}
}
}

C# WPF image load like progressbar

I'v a progressbar and an image.
When Progress Bar value is 50, image loaded by 50%.
I tried to add image as the progressbar foreground, but it have green shade. So ugly.
How can I do this?
To run this sample, you need a snake image which you can get from http://res.freestockphotos.biz/pictures/16/16242-illustration-of-a-green-snake-pv.png. I have used this url directly, but your should download image first and then use it.
You need a control template for your ProgressBar because you want to show percentage status too.
Otherwise normal ProgressBar would do.
Code can be used as is :
<Window x:Class="WpfControlTemplates._32794074.Win32794074"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Win32794074" Height="600" Width="1000">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="397*"/>
<RowDefinition Height="173*"/>
</Grid.RowDefinitions>
<ProgressBar x:Name="PBarCustom" Width="958" Height="200" Maximum="958" Value="958" Foreground="#FFE6E61F" Margin="17,185,17,11.932" ValueChanged="PBarCustom_ValueChanged">
<ProgressBar.Background>
<ImageBrush ImageSource="http://res.freestockphotos.biz/pictures/16/16242-illustration-of-a-green-snake-pv.png"/>
</ProgressBar.Background>
<ProgressBar.Template>
<ControlTemplate>
<Grid Background="{TemplateBinding Background}">
<Rectangle x:Name="Thumb" HorizontalAlignment="Left" Fill="#FFC5EA1F" Stroke="#FF0DB442" Width="{TemplateBinding Width}" />
<Ellipse Fill="#FF7DEEDE" Height="124" Stroke="#FF0DB442" Width="150" VerticalAlignment="Center" HorizontalAlignment="Center" Opacity="0.3"/>
<Label x:Name="tbStatus" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" FontWeight="Bold" FontSize="75" Foreground="#FF21BD76" Content="0" />
</Grid>
</ControlTemplate>
</ProgressBar.Template>
</ProgressBar>
<Button x:Name="BtnLoadSnake" Content="Load Snake" HorizontalAlignment="Left" Margin="462,14.068,0,0" VerticalAlignment="Top" Width="75" Click="BtnLoadSnake_Click" Grid.Row="1"/>
</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Threading;
namespace WpfControlTemplates._32794074
{
/// <summary>
/// Interaction logic for Win32794074.xaml
/// </summary>
public partial class Win32794074 : Window
{
public Win32794074()
{
InitializeComponent();
}
DispatcherTimer timer;
private void BtnLoadSnake_Click(object sender, RoutedEventArgs e)
{
BtnLoadSnake.IsEnabled = false;
PBarCustom.Value = PBarCustom.Maximum;
Rectangle thumb = (Rectangle)PBarCustom.Template.FindName("Thumb", PBarCustom);
thumb.Width = PBarCustom.Value;
Label status = (Label)PBarCustom.Template.FindName("tbStatus", PBarCustom);
status.Content = ((int)(100 - ((100 * PBarCustom.Value) / PBarCustom.Maximum))).ToString();
Dispatcher disp = PBarCustom.Dispatcher;
EventHandler pBarCallbackHandler = new EventHandler(pBarCallback);
timer = new DispatcherTimer(TimeSpan.FromSeconds(0.5), DispatcherPriority.Normal, pBarCallback, disp);
}
private void pBarCallback(object sender, EventArgs e)
{
PBarCustom.Value -= 13;
Rectangle thumb = (Rectangle)PBarCustom.Template.FindName("Thumb", PBarCustom);
thumb.Width = PBarCustom.Value;
Label status = (Label)PBarCustom.Template.FindName("tbStatus", PBarCustom);
status.Content = ((int)(100 - ((100 * PBarCustom.Value) / PBarCustom.Maximum))).ToString();
if (PBarCustom.Value == 0)
timer.Stop();
}
private void PBarCustom_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if(e.NewValue == 0)
BtnLoadSnake.IsEnabled = true;
}
}
}
i had similar scenario.
if you want the scroll bar to be just a rectangle,
easiest way to make it:
1- add an image to your window.
2- put a grid on it in such a way that the grid hides the image.
3- programatically change the width or height of the grid.
tell me if you needed an example code.

WPF Dynamic Listbox with different output

At first I want to say that i searched on internet and I didn't found anything. I would like to make a dynamic song list, that when user adds a song, new object will be added with name and lenght and when he selects this song he would get a path to the selected song. Here is code to understand better:
XAML:
<Window x:Class="ListBox.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ListBox x:Name="SongList" HorizontalAlignment="Left" Height="278" Margin="10,10,0,0" VerticalAlignment="Top" Width="248"/>
<TextBlock HorizontalAlignment="Left" Margin="287,124,0,0" TextWrapping="Wrap" Text="Path" VerticalAlignment="Top" Width="194" Height="22"/>
<Label Content="Song Path" HorizontalAlignment="Left" Margin="287,98,0,0" VerticalAlignment="Top" Width="194"/>
<Button Content="Add Song" HorizontalAlignment="Left" Margin="10,293,0,0" VerticalAlignment="Top" Width="132" Click="Button_Click"/>
</Grid>
and code:
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace ListBox
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog openfile = new OpenFileDialog();
openfile.DefaultExt = ".mp3";
openfile.Filter = "mp3 | *.mp3";
Nullable<bool> result = openfile.ShowDialog();
if (result == true)
{
String file = openfile.FileName;
FileInfo fileinfo = new FileInfo(file);
SongList.Items.Add(fileinfo.Name);
}
}
}
}
so where the "Path" text box is I would like to get current selected song path. Is it possible to make with ItemBox or I need to make array that will save all paths?
I think you should use for your songs, because you're writing a WPF application, an ObservableCollection of your song objects, in order to have a proper ListBox with your updated objects.
Then, you have to create a proper Song class with its own properties, like the SongName or the SongPath. In this class, you will implement the INotifyPropertyChanged interface
and, for each property, you will raise an appropriate OnPropertyChanged event.
With this implementation, once you load a song and add it to the songs list, your ListBox will show the updated collection accordingly.
Further info about the ObservableCollection here.
If you want to have a look at a code sample, in this answer I written an example of developing an ObservableCollection.
at first you might want to have a look at MVVM programming. The concept is not that easy to understand, even harder to apply but once you got it you will be able to create good UI in no-time and it's especially perfect for what you are trying to do.
Now to your problem. FileInfo.Name only stores the file name not the path, so if you don't store the path separately, you won't be able to get it back from just the file name.
KillaKem's solution seems pretty good, however I wouldn't recommend using the Tag property for this. Just create a Collections::Generic::List (please, don't use arrays) class member to store the paths and then use the selectedIndexChange Event to update the PathSearchBox.
using MVVM you could just link the ListBox to a Dictionary which stores both, path and filename and just display the Filename, feel free to research MVVM a bit yourself.
Regards,
Xaser
You could try something along the lines of this,
XAML:
<Window x:Class="ListBox.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ListBox x:Name="SongList" HorizontalAlignment="Left" Height="278" Margin="10,10,0,0" VerticalAlignment="Top" Width="248"/>
<TextBlock HorizontalAlignment="Left" Margin="287,124,0,0" TextWrapping="Wrap" Text="Path" VerticalAlignment="Top" Width="194" Height="22"/>
<Label Name ="pathLabel" Content="Song Path" HorizontalAlignment="Left" Margin="287,98,0,0" VerticalAlignment="Top" Width="194"/>
<Button Content="Add Song" HorizontalAlignment="Left" Margin="10,293,0,0" VerticalAlignment="Top" Width="132" Click="Button_Click"/>
</Grid>
Back Code:
namespace ListBox
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog openfile = new OpenFileDialog();
openfile.DefaultExt = ".mp3";
openfile.Filter = "mp3 | *.mp3";
Nullable<bool> result = openfile.ShowDialog();
if (result == true)
{
String file = openfile.FileName;
FileInfo fileinfo = new FileInfo(file);
SongList.Items.Add(fileinfo.Name);
var pathList = SongList.Tag as List<string>;
pathList.Add(fileinfo.DirectoryName);
SongList.Tag = pathList;
}
}
private void Selection_Changed(object sender, EventArgs e)
{
var myListBox = sender as ListBox;
var myPathList = myListBox.Tag as List<string>;
var filePath = myPathList[myListBox.SelectedIndex];
pathLabel.Content = filePath;
}
}
}
Haven't tested the code but it should be working or close to working.
These is a SelectionChanged event in the listbox you can use. But i would recommend using bi

Combobox not visible to code behind in Silverlight

I have been trying to add items to a comboxbox but cannot seem to get the code behind file to recognize the combobox added to the xaml. I am pretty sure I am missing something simple. Basically the xaml here illustrates an empty combobox. The code behind executes the service, waits for json to come back and deserialize it. Unfortunately I cannot get
xaml:
<navigation:Page x:Class="Growing.Views.Room"
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"
mc:Ignorable="d"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
d:DesignWidth="950" d:DesignHeight="480"
Title="Home" Style="{StaticResource PageStyle}" DataContext="{Binding}" xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">
<Grid x:Name="LayoutRoot" ShowGridLines="True" Background="#FF631C00">
<Grid.ColumnDefinitions>
</Grid.ColumnDefinitions>
<Rectangle Height="298" HorizontalAlignment="Left" Margin="195,94,0,0" Name="rect" Stroke="Black" StrokeThickness="2" VerticalAlignment="Top" Width="582" Fill="#FFAAAAAA" RadiusY="0.25" RadiusX="0.25" />
<sdk:Label Height="38" HorizontalAlignment="Left" Margin="387,160,0,0" Name="label1" VerticalAlignment="Top" Width="203" Content="Select a Room" FontSize="24" FontWeight="Bold" />
<sdk:Label Height="18" HorizontalAlignment="Left" Margin="312,240,0,0" Name="label2" VerticalAlignment="Top" Width="69" Content="Area:" FontSize="14" />
<ComboBox x:Name="RoomAreas" Height="23" HorizontalAlignment="Left" Margin="418,235,0,0" VerticalAlignment="Top" Width="209" />
</Grid>
The code behind:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Runtime.Serialization.Json;
using System.ServiceModel.Web;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Navigation;
using Growing.DataConnectionRef;
namespace Growing.Views
{
public partial class Room : Page
{
public Room()
{
InitializeComponent();
//Asynchronously call the EndReceive Web Service to change the status of an existing open lot record
WebClient GRService = new WebClient();
GRService.DownloadStringCompleted += new DownloadStringCompletedEventHandler(GRService_DownloadStringCompleted);
GRService.DownloadStringAsync(new Uri("/servicestack/GetAreas", UriKind.Relative));
}
static void GRService_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
List<Area> dataList = new List<Area>();
MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(e.Result));
DataContractJsonSerializer ser = new DataContractJsonSerializer(dataList.GetType());
dataList = ser.ReadObject(memoryStream) as List<Area>;
memoryStream.Close();
RoomAreas.ItemSource = dataList;
}
}
}
At RoomAreas.ItemSource I get an error An object reference is required for the non-static field, method, or property 'Growing.Views.Room.RoomAreas'
Sorry if this is hard to follow. Anyone have any ideas what might be going on here?
Thank you in advance!
Make GRService_DownloadStringCompleted method non static:
void GRService_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
List<Area> dataList = new List<Area>();
MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(e.Result));
DataContractJsonSerializer ser = new DataContractJsonSerializer(dataList.GetType());
dataList = ser.ReadObject(memoryStream) as List<Area>;
memoryStream.Close();
RoomAreas.ItemSource = dataList;
}
Try adding ItemsSource="{Binding}" to the combobox property within the Xaml

how to make tooltip move along with mouse?

I am using Silverlight 3 + VSTS 2008. I have a image (Multiscale image control) and I place tooltip on this image. The function of Tooltip works fine. Since the image is big (about 500 * 500 size), and since end user could move mouse on the picture, and I want to display tooltip position along with the mouse (i.e. when mouse moves, I want to tooltip move along with the mouse). Currently, the tooltip displays at a fixed position.
Here is my current XAML code, any ideas how to solve this issue?
<MultiScaleImage x:Name="msi" Height="500" Width="500">
<ToolTipService.ToolTip>
<ToolTip Content="Here is a tool tip" Name="DeepZoomToolTip"></ToolTip>
</ToolTipService.ToolTip>
</MultiScaleImage>
I ended up having a similar issue and solved the issue by using a popup. This post contained the core solution. Here is the suggested XAML from the other post:
<Canvas x:Name="LayoutRoot" Background="White">
<Image Source="/pretty-pretty.png" MouseMove="Image_MouseMove" MouseLeave="Image_MouseLeave"/>
<Popup Name="DeepZoomToolTip">
<Border CornerRadius="1" Padding="1" Background="Azure" IsHitTestVisible="False">
<TextBlock Text="Here is a tool tip" />
</Border>
</Popup>
</Canvas>
And here is the suggested, this would go in the code behind:
private void Image_MouseMove(object sender, MouseEventArgs e)
{
DeepZoomToolTip.IsOpen = true;
DeepZoomToolTip.HorizontalOffset = e.GetPosition(LayoutRoot).X;
DeepZoomToolTip.VerticalOffset = e.GetPosition(LayoutRoot).Y;
}
private void Image_MouseLeave(object sender, MouseEventArgs e)
{
DeepZoomToolTip.IsOpen = false;
}
The tooltip control is designed to pop up roughly where the mouse meets the element to which it's bound, and can't respond to move events. Below is a custom tooltip example. I added the background and the z-index so that the TextBlock would appear over the image. The offset from the mouse position keeps the tooltip away from the mouse cursor, so that the movement is animated smoothly.
XAML:
<UserControl x:Class="ImageEditor.TestControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="800" Height="800">
<Canvas x:Name="MainCanvas">
<Border x:Name="tt" Background="Gray" Visibility="Collapsed" Canvas.ZIndex="10">
<TextBlock x:Name="txtTooltip" Width="90" Height="20" Text="This is a tooltip" ></TextBlock>
</Border>
<Image x:Name="theImage" Source="images/image.jpg" Width="300" MouseEnter="theImage_MouseEnter"
MouseMove="theImage_MouseMove" MouseLeave="theImage_MouseLeave">
</Image>
</Canvas>
</UserControl>
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace ImageEditor
{
public partial class TestControl : UserControl
{
private bool _tooltipVisible = false;
public TestControl()
{
InitializeComponent();
}
private void theImage_MouseMove(object sender, MouseEventArgs e)
{
if (_tooltipVisible)
{
tt.SetValue(Canvas.TopProperty, e.GetPosition(theImage).Y - (5 + txtTooltip.Height));
tt.SetValue(Canvas.LeftProperty, e.GetPosition(theImage).X - 5);
}
}
private void theImage_MouseEnter(object sender, MouseEventArgs e)
{
_tooltipVisible = true;
tt.Visibility = Visibility.Visible;
}
private void theImage_MouseLeave(object sender, MouseEventArgs e)
{
_tooltipVisible = false;
tt.Visibility = Visibility.Collapsed;
}
}
}

Categories

Resources