Modifying image height from context menu in XAML - c#

In my XAML page I define an image with a context menu:
<Image Height="{Binding Image.Height, Mode=TwoWay}" MaxHeight="2000" HorizontalAlignment="Left" StretchDirection="Both" Stretch="Uniform"
Source="{Binding Image.ImageData, Converter={StaticResource ImageByteConverter}}"
x:Name="Image1">
<Image.ContextMenu>
<ContextMenu>
<MenuItem Header="200" Click="ImageHeight200_Click" />
<MenuItem Header="400" Click="ImageHeight400_Click" />
<MenuItem Header="600" Click="ImageHeight600_Click" />
<MenuItem Header="800" Click="ImageHeight800_Click" />
<MenuItem Header="1000" Click="ImageHeight1000_Click" />
</ContextMenu>
</Image.ContextMenu>
</Image>
Now I want to add code to resize the image.
When I write something like this
private void ImageHeight200_Click(object sender, RoutedEventArgs e)
{
var img = (Image)e.Source;
img.Height = 200;
}
It accesses the MenuItem but not the image and I get an error message:
The object of type "System.Windows.Controls.MenuItem" cannot be converted to type "System.Windows.Controls.Image".
My Question is:
How can I access the image object?

You can just reference the image by name
private void ImageHeight200_Click(object sender, RoutedEventArgs e)
{
Image1.Height = 200;
}

You could use PlacementTarget property of ContextMenu
private void ImageHeight200_Click(object sender, System.Windows.RoutedEventArgs e){
MenuItem mnu = sender as MenuItem;
Image sp = null;
if(mnu!=null)
{
sp = ((ContextMenu)mnu.Parent).PlacementTarget as Image;
}}

Related

wpf textblock focus on mouse right click

hello I am pretty new to wpf c#, I have a treeview which is populated at run time and here is my xaml code
<StackPanel Orientation="Horizontal">
<Image Source="Properties\accessories-text-editor-6.ico" Margin="0,0,5,0" />
<TextBlock Text="{Binding Name}" Foreground="Green" MouseLeftButtonDown="TextBlock_MouseLeftButtonDown" MouseRightButtonDown="TextBlock_MouseRightButtonDown" >
<TextBlock.ContextMenu>
<ContextMenu>
<MenuItem Header="HeadLine" ></MenuItem>
<MenuItem Header="Textblock" ></MenuItem>
<MenuItem Header="Author" ></MenuItem>
<MenuItem Header="PageNumber" ></MenuItem>
<MenuItem Header="RunningTitle" ></MenuItem>
<MenuItem Header="Illustration" ></MenuItem>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</StackPanel>
what I want is when I right click the textblock that is inside the treeview. the textblock need to be focus. As of now what it does is show the context menu item.
so how do I get the index of the Right clicked textblock? so I can focus to that item.
Thank you
A TextBlock cannot be focused...but you can get a reference to it in the MouseRightButtonDown event handler by casting the sender argument:
private void TextBlock_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
TextBlock txt = sender as TextBlock;
//do whatever you want with the TextBlock...
}
If you are in the context of a TreeView you may want to select the parent TreeViewItem:
private void TextBlock_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
TextBlock txt = sender as TextBlock;
TreeViewItem tvi = FindParent<TreeViewItem>(txt);
if (tvi != null)
tvi.IsSelected = true;
}
private static T FindParent<T>(DependencyObject dependencyObject) where T : DependencyObject
{
var parent = VisualTreeHelper.GetParent(dependencyObject);
if (parent == null) return null;
var parentT = parent as T;
return parentT ?? FindParent<T>(parent);
}

Getting child element in XAML by type

I have xaml button like so:
<Button Click="SyncToDeviceToggle_OnClick">
<Button.Template>
<ControlTemplate>
<Image Source="Img/kin.png" Height="25"/>
</ControlTemplate>
</Button.Template>
</Button>
Code behind:
private void SyncToDeviceToggle_OnClick(object sender, RoutedEventArgs e)
{
var image = ??//I want to get the child image element in the button without having to search for it by name specified in name="something"
}
In javascript i would just do
button.getElementsByTagName("image")[0];
You could assign a name to the Image control and then access it by means of the FindName method of the Button's Template:
<ControlTemplate>
<Image x:Name="image" Source="Img/kin.png" Height="25"/>
</ControlTemplate>
...
private void Button_Click(object sender, RoutedEventArgs e)
{
var control = (Control)sender;
var image = control.Template.FindName("image", control) as Image;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Button button = sender as Button;
DependencyObject child = VisualTreeHelper.GetChild(button, 0);
Image image = child as Image;
//Now you can access your image Properties
}
<Button Click="SyncToDeviceToggle_OnClick" Margin="0,224,0,302">
<Button.Background>
<ImageBrush ImageSource="Img/kin.png" x:Name="MyBrush"/>
</Button.Background>
</Button>
If done in this way, you can directly access MyBrush by its direct name in the .cs file.

How to use (if possible) same source a tap event uses in a ContextMenu button click?

Im tweaking a Sound Player app to try and include a Save as Ringtone function. App uses Tiles and a Viewmodel. Tapping each tile plays a sound. I added a Context Menu to the Data Template to give the option on a Tap and Hold event to save that sound as a Ringtone. I am having some issues figuring out just how to use the same source as the Tiles use to play the sound. Below, first code is portion of the Mainpage.xaml. Then the c# code. What I have set at the bottom of the MainPage.cs for the _customRingtone Source is wrong. The emulator stops at "SoundData data = selector.SelectedItem as SoundData;" I cant figure out how to do the source in a similar way the Tile taps get the audio for playing it. I didnt post the ViewModel but can if you want me to. That is where the Tile Groups and sounds are loaded.
<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Key="SoundTileDataTemplate">
<StackPanel>
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu>
<toolkit:MenuItem Click="Save_Click" Header="Save as Ringtone" />
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
<Grid Background="{StaticResource PhoneAccentBrush}"
Margin="0, 0, 12, 12">
<Grid VerticalAlignment="Top"
HorizontalAlignment="Right"
Width="40"
Height="40"
Margin="0, 6, 6, 0">
<Ellipse Stroke="{StaticResource PhoneForegroundBrush}"
StrokeThickness="3" />
<Image Source="/Assets/AppBar/Play.png" />
</Grid>
<StackPanel VerticalAlignment="Bottom">
<TextBlock Text="{Binding Title}" Margin="6, 0, 0, 6" />
</StackPanel>
</Grid>
</StackPanel>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<MediaElement
Name="AudioPlayer"
Volume="1" />
<!--Pivot Control-->
<phone:Pivot Title="{Binding Path=LocalizedResources.ApplicationTitle,
Source={StaticResource LocalizedStrings}}">
<phone:PivotItem Header="{Binding Animals.Title}">
<phone:LongListSelector x:Name="Animal"
SelectionChanged="LongListSelector_SelectionChanged"
Margin="0,0,-12,0"
ItemsSource="{Binding Animals.Items}"
LayoutMode="Grid"
GridCellSize="150,150"
ItemTemplate="{StaticResource SoundTileDataTemplate}"
/>
</phone:PivotItem>
public partial class MainPage : PhoneApplicationPage
{
private readonly SaveRingtoneTask
_CustomRingtone;
// Constructor
public MainPage()
{
InitializeComponent();
// Set the data context of the listbox control to the sample data
DataContext = App.ViewModel;
_CustomRingtone = new SaveRingtoneTask();
_CustomRingtone.Completed +=
customeRingtone_Completed;
BuildLocalizedApplicationBar();
}
// Load data for the ViewModel Items
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (!App.ViewModel.IsDataLoaded)
{
App.ViewModel.LoadData();
}
}
private void LongListSelector_SelectionChanged(object sender,
SelectionChangedEventArgs e)
{
LongListSelector selector = sender as LongListSelector;
// verifying our sender is actually a LongListSelector
if (selector == null)
return;
SoundData data = selector.SelectedItem as SoundData;
// verifying our sender is actually SoundData
if (data == null)
return;
private void customeRingtone_Completed(object sender, TaskEventArgs e)
{
if (e.TaskResult == TaskResult.OK)
{
MessageBox.Show(#"Saved");
}
else if (e.TaskResult == TaskResult.Cancel)
{
MessageBox.Show(#"Canceled");
}
else
{
MessageBox.Show(#"Not Saved");
}
}
private void Save_Click(object sender, System.Windows.RoutedEventArgs e)
{
LongListSelector selector = sender as LongListSelector;
SoundData data = selector.SelectedItem as SoundData;
**_CustomRingtone.Source = new Uri(data.FilePath, UriKind.RelativeOrAbsolute**);
_CustomRingtone.DisplayName = "Ring";
_CustomRingtone.Show();
}
You Save_Click event handler is not passed a LLS, but a context MenuItem. The DataContext of the MenuItem is the object you are after.
private void Save_Click(object sender, System.Windows.RoutedEventArgs e)
{
var element = (FrameworkElement)sender;
SoundData data = element.DataContext as SoundData;
_CustomRingtone.Source = new Uri(data.FilePath, UriKind.RelativeOrAbsolute**);
_CustomRingtone.DisplayName = "Ring";
_CustomRingtone.Show();
}

windows phone 8 imagebrush getting path

i have this code
<Grid Width="160" x:Name="grd">
<Grid.Background>
<ImageBrush x:Name="img" ImageSource="Assets/Icons/tab-inactive.png" />
</Grid.Background>
<TextBlock x:Name="txtacticve" Text="Rating" Tap="TextBlock_Tap_1" />
</Grid>
while tapping the textblock the tap event will be called.how can i get the complete path of the imagesource in this tap event in code behind? i am really at the lost here how to get to the imagesource in my codebehind event.
One solution could be the following one :
In your XAML code, you can bind your TextBlock.Tag property to the Grid.Background property you need. It could be useful to do it in XAML rather than code behind if your Grid is not the first parent (no need to find the required parent with recursive C# code) :
<Grid Width="160" x:Name="grd">
<Grid.Background>
<ImageBrush x:Name="img" ImageSource="Assets/Icons/tab-inactive.png" />
</Grid.Background>
<TextBlock x:Name="txtacticve" Text="Rating" Tap="TextBlock_Tap_1" Tag="{Binding ElementName=grd, Path=Background}" />
</Grid>
Then in your code behind, you just have to cast and use the TextBlock.Tag property that way :
private void TextBlock_Tap_1(object sender, System.Windows.Input.GestureEventArgs e)
{
var textBlock = sender as TextBlock;
if (textBlock != null)
{
var test = ((BitmapImage)((ImageBrush)textBlock.Tag).ImageSource).UriSource.OriginalString;
}
}
Try this.
private void TextBlock_Tap_1(object sender, System.Windows.Input.GestureEventArgs e)
{
var grid = (Grid)txtacticve.Parent;
var img = grid.Background;
var path = ((BitmapImage)(((ImageBrush)(img)).ImageSource)).UriSource.AbsolutePath;
}

ContextMenu disappears immediately after appearing

I have a context menu but it is disappearing instantly after it shows up.
<TextBlock Name="InputtedAddress" Text="{Binding Path=InputtedAddress}" MouseDown="InputtedAddress_MouseDown"/>
System.Windows.Controls.ContextMenu thisMenu;
private void InputtedAddress_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.RightButton == MouseButtonState.Pressed)
{
thisMenu = new System.Windows.Controls.ContextMenu();
MenuItem thisMenuItem = new MenuItem() { Header = "Zoom to Incident" };
thisMenuItem.Click += new RoutedEventHandler(thisMenuItem_Click);
thisMenu.Items.Add(thisMenuItem);
thisMenu.IsOpen = true;
}
}
It's likely because you're not marking the MouseDown event to handled. Set e.Handled to true and it will no longer propagate and your ContextMenu will stay open.
That said, this is an awful way to assign a ContextMenu in the first place. Why not just do this:
<TextBlock ...>
<TextBlock.ContextMenu>
<ContextMenu>
<MenuItem Header="Zoom to Incident" Click="thisMenuItem_Click"/>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
You should assign your menu to the ContextMenu property of your TextBlock so that the opening and positioning will be taken care of for you. You also don't need to create the menu in each MouseDown; just create it once and assign it to the ContextMenu property.
In XAML:
<TextBlock
Name="InputtedAddress"
Text="{Binding Path=InputtedAddress}"
>
<TextBlock.ContextMenu>
<ContextMenu>
<MenuItem
Header="Zoom to Incident"
Click="ContextMenu_Click"
/>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
If you do want to show it manually you will need to position it before showing it by setting the PlacementTarget property, something like this:
private void InputtedAddress_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.RightButton == MouseButtonState.Pressed)
{
thisMenuPlacementTarget = InputtedAddress;
thisMenu.IsOpen = true;
}
}
P.S. "Inputted" is not a word :)

Categories

Resources