Blend4, How to make WPF App(button show up pic) - c#

How to make a button let a picture show up ?
what i Need to do, is creating 300 buttons each of these buttons will represent a unique path and pic every pic is defferent than the other? Unfortunately, WPF SketchFlow or Silverlight SketchFlow (I don't know the difference) can not be running as a program on computer. so what left is WFP app. Furthermore, i find it so difficult to just create one button linked to a pic's path!!!!.
I watched all of the Microsoft training Videos(the 5 days ones, if u dont know what i mean)http://www.microsoft.com/expression/resources/blendtraining/ . And still cant do it. I was searching for almost 4 weeks, and i still do.
Any idea how to create this essay app which require lots of work.
summery: 1-I don't know which app to use Silverlight or WPF app?(I don't know the difference)
2-i need to create a button that when i press on it, (New sorry) there will be a pic showing up in certain place that ill choose).
so in the end i need the code that will let the button work. direction for further info that ill need(websites that include vids or training by any type)
My regards SHeeDeED :)

Maybe you should start with a simple program: 1 button, showing 1 picture.
Handcraft it in XAML (no blend) and when you're stuck post a specific question here with the code.

I use Blend for most of my XAML/WPF UI design, and it works pretty well for me. I did, however, learn WPF and XAML by writing it longhand in the Visual Studio designer first. For any coding other than XAML (VB.NET, C#, C++, etc) I would highly suggest using Visual Studio as there are no bells and whistles in the Blend code window. It is essentially a colorful text editor.
As for buttons displaying images I have a couple of questions. I imagine your buttons are going to be loaded from a collection of some objects or something. By far, this is better than specifying each button in the XAML code.
I will assume your collection of objects has an ImagePath (or similarly named) property. The following should work out alright.
Load your ListBox with the Items, (see either http://www.WindowsClient.net for the old [Windows Forms] way, or read up on MVVM for the newer better way). Below is my listbox; ItemsSource is bound to the ImageCollection property on my ViewModel in this case. The items in my Imagecollection have an ImagePath property that is just a string file path to the image.
<ListBox ItemTemplate="{DynamicResource MyImageButton}" ItemsSource="{Binding ImageCollection}"/>
In Blend, you can create a DataTemplate by right clicking on the listBox, and going to Edit Additional Templates > Edit Generated Items (ItemTemplate).
From there you are just editing the layout of the items that will be created in the listbox. Below is my example of an item button with an image bound to the ImagePath property.
<DataTemplate x:Key="MyImageButton">
<Button Width="75">
<Button.Content>
<StackPanel>
<Image Source="{Binding ImagePath}" HorizontalAlignment="Left" Height="64" Width="64"/>
</StackPanel>
</Button.Content>
</Button>
</DataTemplate>
Let me know if you need more info and I can post some more resource links.
EDIT
Alright, so here is a simple little application that I made to illustrate how this can be done probably the easiest as possible. In this application, I have 3 classes:
ImageButton - It just consists of two string properties, ImagePath and ImageName.
ImageButtonCollection - Inherited from ObservableCollection, creates and adds 300 buttons (iterates 1 to 300 and sets ImagePath to "C:\Images\image{i}.png" and ImageName to "image{i}".
The MainWindow class - I will post the contents below.
MainWindow.xaml
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ImageButtons"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="MainWindow"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<CollectionViewSource x:Key="ImageButtonsCVS"/>
</Window.Resources>
<Grid>
<ListBox Height="311" HorizontalAlignment="Left" x:Name="ListBox1" VerticalAlignment="Top" Width="268" HorizontalContentAlignment="Stretch">
<ListBox.Resources>
<DataTemplate DataType="{x:Type local:ImageButton}">
<Border Background="#5A000000" CornerRadius="5">
<Grid Height="Auto">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button Grid.ColumnSpan="1" Height="30" Width="30" BorderBrush="#38FFFFFF" BorderThickness="1" Margin="5" Padding="0">
<Image Source="{Binding ImagePath}"/>
</Button>
<TextBlock Margin="0" TextWrapping="Wrap" Text="{Binding ImageName}" d:LayoutOverrides="Width, Height" Grid.Column="1" VerticalAlignment="Center" Foreground="White"/>
</Grid>
</Border>
</DataTemplate>
</ListBox.Resources>
<ListBox.ItemsSource>
<Binding Source="{StaticResource ImageButtonsCVS}"/>
</ListBox.ItemsSource>
</ListBox>
<Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="322,54,0,0" x:Name="Button1" VerticalAlignment="Top" Width="75" Click="CreateButtons" />
</Grid>
MainWindow.xaml.vb - I am more familiar with VB, but this can be easily ported to C# or whatever.
Class MainWindow
Private Sub CreateButtons(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
Dim ImageButtonCVS As CollectionViewSource = Me.FindResource("ImageButtonsCVS")
ImageButtonCVS.Source = New ImageButtonCollection
End Sub
End Class
So, the ListBoxes ItemsSource property is bound to the CollectionViewSource created in the Window.Resources. The ListBox also has in it's resources a DataTemplate for the ImageButton class. Anytime an ImageButton is displayed in that listbox, that template will be used. The buttons click event is set to the CreateButtons method in the codebehind.
That method finds the CollectionViewSource resource, and sets it's source to a new instance of the ImageButtonCollection class. Once that is done, the UI is notified of an update (since the ObservableCollection has built in UI notification) and changes accordingly displaying 300 buttons with a little textblock next to them with the image name.
If you run this, create a folder on your C drive with some images named "imageX.png" with x being a number 1 to 300. Below are the other two classes so you can create/compile/run it.
ImageButton class
Public Class ImageButton
Public Property ImagePath As String
Public Property ImageName As String
Public Sub New()
End Sub
Public Sub New(ByVal Path As String, ByVal Name As String)
Me.ImagePath = Path
Me.ImageName = Name
End Sub
End Class
ImageButtonCollection class
Imports System.Collections.ObjectModel
Public Class ImageButtonCollection
Inherits ObservableCollection(Of ImageButton)
Public Sub New()
For i As Integer = 1 To 300
Me.Add(New ImageButton(String.Format("C:\Images\image{0}.png", i), String.Format("Image{0}", i)))
Next
End Sub
End Class
You never specified how you wanted the image displayed. You may not want them to be in a listbox. The beauty of WPF is that once you get it working in a listBox or whatever ItemsControl, you can easily change to another ItemsControl, or even customize one. Go into the ListBox template and change the ItemsHost to use a uniform grid or to stack items horizontally instead of vertically.

Related

UI not updating using MVVM toolkit in WinUI 3

I am trying to change the size of a grid using data binding in order to be able to expand certain sections of my UI. I have looked online and nothing really seems to work. My window has a frame that loads a "root page" with another frame inside of it as seen in rootpage.xaml below. I have added a textbox but that does not seem to work. Interestingly enough, when I click the button present on the page. I do get a line outputted so my code is running. Adding a breakpoint shows similar results that the property FullScreenValue does in fact change. I think I am missing something in order to get the PropertyChanged event to be received or I may be unintentionally instancing multiple instances of my ViewModel. Looking for a solution.
My root page loaded into the frame in my window:
<Page
x:Class="MVVM.Views.rootPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MVVM.Views"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:ViewModels="using:MVVM.ViewModels"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.DataContext>
<ViewModels:RootPageViewModel x:Name="ViewModel"/>
</Page.DataContext>
<Grid x:Name="frameGrid" ColumnDefinitions="*, *" RowDefinitions ="*, *" Grid.Row="1" Margin="15, 0, 15, 0" >
<Frame x:Name="topleftFrame" Grid.Column="0" Grid.Row="0" CornerRadius="8" Margin="10, 10, 10, 10" Grid.ColumnSpan="{Binding FullScreenValue,Mode=OneWay}" Grid.RowSpan="{Binding FullScreenValue, Mode=OneWay}"/>
<AppBarButton Icon="FullScreen" Grid.Column="0" Grid.Row="0" VerticalAlignment="Top" HorizontalAlignment="Right" Margin="10,5,5,10" Command="{Binding FullScreenCommand, Mode=OneWay}"/>
Visibility="Visible"/>
<TextBlock Text="{Binding FullScreenValue, Mode=OneWay}" Grid.Row="1" Grid.Column="1"/>
</Grid>
</Page>
My ViewModel:
namespace MVVM.ViewModels
{
public partial class RootPageViewModel : ObservableObject
{
[ObservableProperty]
private int fullScreenValue;
public RootPageViewModel()
{
fullScreenValue = 1;
}
[ICommand]
void FullScreen()
{
fullScreenValue = 2;
Debug.WriteLine("HI");
}
}
}
As you can see I am trying to make use of the community toolkit. I have tried replacing some of these generated snippets with standard mvvm properties and commands to no avail. If I change the constructor to have a value of 2 I get my desired result, but can't seem to do it with this button! Send help.
My desired result is upon clicking the button, the frame will now span 2 columns and 2 rows instead of 1 column and 1 row. Maybe because this sort of UI concerns strictly the view it does not necessarily need a ViewModel but nonetheless I am still looking for help as I feel like I will run into this problem in the future. I am new to a lot of things in the Microsoft ecosystem so please forgive me if this is a repeat question and I just could not understand other answers.

What is the equivalent way to use Bitmap,Graphics,PictureBox & BitmapCopy() in WPF?

I'll try to explain my problem clearly.
I have a working code in WinForms that has a Board (PictureBox) that shows an image thats generated from a list of users controls (win-forms) by the function UserControl.BitmapCopy() for each user control.
This process begins with a blank image (Graphic type), and for each user control I draw it in a specific location with the function BitmapCopy() of the user control.
The result is an image that looks like a real form (with buttons,labels,etc.), but it’s just an image.
Then I show this image in a picture Box.
Now I need to implement this code in WPF, but I can’t generate an image of each user control with BitmapCopy().
I found this code that does it, so now I can generate a bitmap for each user control, but I don’t know what is the best way to create the Big Board that eventually shows a bitmap that has all the user controls images inside it, in different locations.
I would appreciate any help.
This is the equivalent in WPF:
<Window x:Class="MiscSamples.VisualBrush"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="VisualBrush" Height="300" Width="300" x:Name="Window">
<StackPanel>
<TextBlock Text="Hi, Im a Window!"/>
<TextBox Text="This is a TextBox"/>
<Slider Width="200"/>
</StackPanel>
<Window.ToolTip>
<ToolTip DataContext="{Binding PlacementTarget, RelativeSource={RelativeSource Self}}">
<Grid Height="400" Width="400">
<Grid.Background>
<VisualBrush Visual="{Binding}"/>
</Grid.Background>
</Grid>
</ToolTip>
</Window.ToolTip>
</Window>
The Window's ToolTip consists of a grid painted with VisualBrush whose Visual is the Window itself. It looks like this:
As you can see, Exactly 0 lines of C# code are required to achieve the same in WPF.

Why do my TextBoxes in different tabs of a TabControl lose their undo history?

I have a TabControl with TextBox controls in the ContentTemplate. When I type some text in one tab and switch to another tab, the Undo history in the original tab is gone when I go back.
Another problem that comes up is any text that was selected is deselected and the caret moves to the beginning of the TextBox.
If I make a window with just hardcoded TabItem controls, the undo history is preserved. The issue has something to do with my binding or templates.
Here is my XAML for the main window
<Window x:Class="TabbedTextAreaTest.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>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Button Command="{Binding AddNewTab}">Add Tab</Button>
<TabControl ItemsSource="{Binding Tabs}" Grid.Row="1">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Header}"/>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<TextBox Text="{Binding Content, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
</Grid>
</Window>
Is there a way to preserve the undo/redo history and selected text when switching tabs without manually catching those commands?
When you use a TabControl which gets its tabs via databinding on ItemsSource, WPF doesn't keep the visual tree for each item around as you switch. Thus, when you switch from tab 1 to tab 2, then back to tab 1, the controls on tab 1 are not actually the same control instances which you saw on tab 1 the first time.
There are a number of ways around to deal with this - TabControls which have explicit TabItem instances do keep their visual trees when you switch tabs, so probably the easiest way to do it is to wrap your collection of tab items in something which makes TabItems for them.
Unfortunately right now I can't find a link to an example of how to do this. There are references to articles elsewhere on SO, but they all seem to point to pages which no longer exist, and I don't have time to dig any deeper.
The reason is simple. If you think the both operation you complain about are strictly UI operations: Undo: user editing on the UI control, selection: selection of the text on UI control.
When you swicth Tab to another and go back, what happens in WPF is that all controls are rebinded to there data (ModelView normally, or just Model) again, as if you was showing them for the first time. So they loose their UI appearance attributes.
To manage that correctly in Tab environment in WPF you need to manage Undo/Redo stack by your own.
Good luck.

c# WPF how to produce a flashy warning

I'm learning WPF, so bear with me.
I would like to have my WPF application flash in the user's face if a certain event is fired.
What is the best way to "notify" the user? I really want the user to react!
Cheers, Patrick
Environment: Windows7/64bit/.Net4
If you want the user to react you can force them to by simply opening a modal dialogue. The most lightweight of which being the MessageBox. You can also create normal modal windows using their ShowDialog method, you can make those windows as "fancy" as you want by getting rid of their normal appearance. This is achieved by setting the WindowStyle to None and AllowsTransparency to true, this will remove all the frame elements, so the window is now pure content.
Popups are handy for non-modal notifications and they already are content-only, but setting their AllowsTransparency to true may also be desired if you want rounded corners for example.
Best is entirely subjective and depends on many context variables but here is how I do it MVVM style.
In your main view model, define a property
pubic ObservableCollection<AlertViewModel"> Alerts { get; private set; }
in my case the AlertViewModel has only a "Message" property and a "Dismiss" RelayCommand.
In the XAML of your main view add
<Grid>
<all of my other other view controls>
<ItemsControl x:Name="AlertsControl" Opacity="50" ItemsSource="{Binding Alerts}"/>
</Grid>
Make sure it is the last item in the main container of your main view. This ensures it has the highest z order and will appear on top of all other controls.
Here is the data template for this view model
<DataTemplate DataType="{x:Type vm:AlertViewModel}">
<Border CornerRadius="10" Margin="3" Background="Red">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="75"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Margin="10" Grid.Column="0"
Command="{Binding ElementName=theWindow, Path=DataContext.DismissAlarmCommand}"
CommandParameter="{Binding}">Dismiss</Button>
<TextBlock Foreground="White" FontWeight="ExtraBold" Grid.Column="1"
Text="{Binding Message}" FontSize="20"
VerticalAlignment="Center" HorizontalAlignment="Left"></TextBlock>
</Grid>
</Border>
</DataTemplate>
Now,
Alerts.Add( new AlertViewModel() { Message = "Danger Will Robinson! Danger!" } );
Will pop a Bright red alert box onto the top of your main form. It does not go away until the user presses "Dismiss"
If you want it to flash or fade in and out or bounce up and down you can add animation in the data template.
You can use a Converter or data to Enable/Disable the rest of the controls in the app byt binding to AlertsControl.HasItems
Good luck.

access-like data navigation in WPF?

What would be the best way to build a data-navigation like in access-forms in XAML/C#?
Should I build a user control (or even custom control) that I just bind to my collection in which I can put other controls? (hence this question: C# User Control that can contain other Controls (when using it) )
Or can I build something by deriving from then ItemsControl somehow? how?
Or would this be done completely different today (like "this style of navigation is so last year!")?
I'm relatively new to C# and all (not programming as such, but with more like "housewife-language" Access-VBA) also I'm no native english speaker. So pls be gentle =)
You can create user control and place a bunch of buttons (First, Prev, Next, Last, etc..) in it and place it on the main window. Secondly, you can bind your data navigation user control to a CollectionViewSource which will help you to navigate among your data.
Your main window:
<Window.Resources>
<CollectionViewSource x:Key="items" Source="{Binding}" />
</Window.Resources>
<Grid>
<WpfApplication1:DataNavigation DataContext="{Binding Source={StaticResource items}}" />
<StackPanel>
<TextBox Text="{Binding Source={StaticResource items},Path=Name}" />
</StackPanel>
</Grid>
Your Data Navigation User Control:
<StackPanel>
<Button x:Name="Prev" Click="Prev_Click"><</Button>
<Button x:Name="Next" Click="Next_Click">></Button>
<!-- and so on -->
</StackPanel>
And your click handlers goes like this:
private void Prev_Click(object sender, RoutedEventArgs e)
{
ICollectionView view = CollectionViewSource.GetDefaultView(DataContext);
if (view != null)
{
view.MoveCurrentToPrevious();
}
}
I hope this helps.
Sounds like you're after a DataGrid control. Microsoft is releasing a WPF DataGrid as part of a WPF Toolkit which you can download here: http://wpf.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=25047.

Categories

Resources