I am creating UWP app, and I maked external arrow "marker" of selected item in listview...
Like this:
I have managed to achieve this with next code:
var current = lvMain.Items.FirstOrDefault(a => (a as MyModel).Selected) as MyModel;
ListViewItem selected = lvMain.ContainerFromItem(current) as ListViewItem;
GeneralTransform generalTransform1 = gvEpg.TransformToVisual(selected);
Point currentPoint = generalTransform1.TransformPoint(new Point());
In Scroll change event I am calling this and set the arrow position by the Point of my item. And this is working.
But, I want to simplified this. Is there any kind of binding or something like that, that would make arrow always follow the item?
Here's the sample.
XAML MainPage:
<Page.Resources>
<DataTemplate x:Key="DataTemplate">
<Canvas Height="80" Width="200">
<TextBlock Text="{Binding}"/>
</Canvas>
</DataTemplate>
</Page.Resources>
<StackPanel Orientation="Horizontal">
<ListView x:Name="ListView" Width="400"
SelectionChanged="ListView_OnSelectionChanged"
ItemTemplate="{StaticResource DataTemplate}"/>
<Canvas x:Name="ParentCanvas">
<Image x:Name="Arrow"
Stretch="UniformToFill" Width="200" Height="80"
Source="Assets/Red_Left_Arrow.png"/>
</Canvas>
</StackPanel>
Code behind:
private readonly List<string> _names = new List<string>();
private Visual _rectangleVisual;
private Visual _parentVisual;
public MainPage()
{
InitializeComponent();
Loaded += MainPage_Loaded;
}
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
for (int i = 0; i < 32; i++)
{
_names.Add("item " + i);
}
ListView.ItemsSource = _names;
_parentVisual = ElementCompositionPreview.GetElementVisual(ParentCanvas);
_rectangleVisual = ElementCompositionPreview.GetElementVisual(Arrow);
var border = VisualTreeHelper.GetChild(ListView, 0) as Border;
var scrollViewer = border.Child as ScrollViewer;
var scrollerProperties = ElementCompositionPreview.GetScrollViewerManipulationPropertySet(scrollViewer);
var offsetExpressionAnimation = _rectangleVisual.Compositor.CreateExpressionAnimation("Scroller.Translation.Y");
offsetExpressionAnimation.SetReferenceParameter("Scroller", scrollerProperties);
_rectangleVisual.StartAnimation("Offset.Y", offsetExpressionAnimation);
}
private void ListView_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
var listViewItem = ListView.ContainerFromItem(ListView.SelectedItem) as ListViewItem;
var listItemVisual = ElementCompositionPreview.GetElementVisual(listViewItem);
_parentVisual.Offset = new Vector3(_parentVisual.Offset.X, listItemVisual.Offset.Y, 0);
}
Looks like what you asked for:
Related
So, I have a main WrapPanel called "valoresPanel". When I start running I need to click the Button labeled "2" (below) and a TextBox needs to appear inside the WrapPanel labeled "1" thats was created in runtime.
This is my code for the "+ button" right now:
void novoValor_Click(object sender, RoutedEventArgs e)
{
WrapPanel wpValores = new WrapPanel();
Button deleteValor = new Button();
TextBox txtValor = new TextBox();
deleteValor.Height = 25;
deleteValor.Width = 25;
deleteValor.Content = "X";
txtValor.Height = 25;
txtValor.Width = 70;
txtValor.Margin = new Thickness(0, 0, 8, 0);
wpValores.Height = 25;
wpValores.Width = 105;
wpValores.Children.Add(deleteValor);
wpValores.Children.Add(txtValor);
valoresPanel.Children.Add(wpValores);
deleteValor.Click += deleteValor2_Click;
}
So, i updated my code using only one WrapPanel per item, now i can add a item, add values and delete the item with its respective values but i cant delete a specific value, this is my code by now:
this image will help to understand
void novoValor_Click(object sender, RoutedEventArgs e)
{
Button btn = sender as Button;
WrapPanel wpFather = btn.Parent as WrapPanel;
WrapPanel wpValue = new WrapPanel();
Button deleteValue = new Button();
TextBox txtValue = new TextBox();
wpValue.Height = 25;
wpValue.Width = 105;
deleteValue.Height = 25;
deleteValue.Width = 25;
deleteValue.Content = "-";
txtValue.Height = 25;
txtValue.Width = 70;
txtValue.Margin = new Thickness(0, 0, 8, 0);
wpValue.Children.Add(deleteValue);
wpValue.Children.Add(txtValue);
wpFather.Children.Add(wpValue);
deleteValue.Click += deleteValor_Click;
}
void deleteValor_Click(object sender, RoutedEventArgs e)
{
Button btn = sender as Button;
WrapPanel panel = btn.Parent as WrapPanel;
entradasPanel.Children.Remove(panel);
}
If someone need any other information im willing to send it as fast as I can!
You should create a ListView which has a WrapPanel as ItemsPanel. Then to the ListView.ItemsSource you bind an ObservableCollection of data models. By defining a DataTemplate for the ListView.ItemTemplate you can make the data items be displayed as a TextBox with a Button where the TextBox binds to this item's data model. By pressing the delete button you simply remove this data model from the ObservaleColection ( the ItemsSource of the ListView).
DataModel.cs
class DataModel
{
public string UserInput { get; set; }
}
ViewModel.cs
class ViewModel
{
public ObservableCollection<DataModel> Items { get; set; }
public ICommand AddItemCommand => new AsyncRelayCommand(() => this.Items.Add(new DataModel()));
public ICommand RemoveItemCommand => new AsyncRelayCommand((item) => this.Items.Remove(item));
public ViewModel()
{
this.Items = new ObservableCollection<DataModel>();
}
}
MainWindow.xaml
<Window>
<Window.DataContext>
<ViewModel />
</Window.DataContext>
<StackPanel>
<Button Content="Add Item"
Command="{Binding AddItemCommand}" />
<ListView ItemsSource="{Binding Items}">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Width="600" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate DataType="{x:Type DataModel}">
<StackPanel Orientation="Horizontal">
<Button Content="Remove Item"
Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ListView}, Path=DataContext.RemoveItemCommand}"
CommandParameter="{Binding}" />
<TextBox Text="{Binding UserInput}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
</Window>
I could solve my last question with the following code:
void deleteValue_Click(object sender, RoutedEventArgs e)
{
Button btn = sender as Button;
WrapPanel panel = btn.Parent as WrapPanel;
WrapPanel panelPai = panel.Parent as WrapPanel;
panelPai.Children.Remove(panel);
}
I develop one-page app. This is XAML of MainPage
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<StackPanel Orientation="Vertical" Grid.Row="0">
<AppBar x:Name="MenuAppBar" IsOpen="True">
<StackPanel Orientation="Horizontal">
<AppBarButton Icon="Add" Label="Добавить лексемы" Name="AddLexemesFromFolder" Click="OpenFolderAndGetLexemes_Click" HorizontalAlignment="Left"/>
<AppBarButton Icon="Save" Label="Сохранить лексемы" Name="SaveLexemes" Click="SaveLexemes_Click" HorizontalAlignment="Left"/>
</StackPanel>
</AppBar>
</StackPanel>
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto" VerticalScrollMode="Enabled">
<Grid x:Name="GridLexemesViewer" HorizontalAlignment="Stretch"/>
</ScrollViewer>
</Grid>
When I pressed "AddLexemesFromFolder" button more than two times, GridLexemesViewer is getting smaller over and over.
This is OpenFolderAndGetLexemes code
private async void OpenFolderAndGetLexemes_Click(object sender, RoutedEventArgs routedEventArgs)
{
await StartSaveLexemes();
var folderPicker = new Windows.Storage.Pickers.FolderPicker();
folderPicker.FileTypeFilter.Add("*");
Windows.Storage.StorageFolder folder = await folderPicker.PickSingleFolderAsync();
if (folder != null)
{
StorageApplicationPermissions.FutureAccessList.AddOrReplace("PickedFolderToken", folder);
await Task.Run(() => StartNewSessionForGetLexemes(folder.Path));
InitializeGrid();
}
}
I use "InitializeGrid" method for clear Children in GridLexemesViewer, use CreateRowsAndColumns and put TextBox with content to GridLexemesViewer.
This is code of InitializeGrid and CreateRowsAndColumns()
private void InitializeGrid()
{
GridLexemesViewer.Children.Clear();
CreateRowsAndColumns();
int index = 1;
foreach (var lexem in CurrentSession.Lexemes)
{
foreach (var item in lexem.Value)
{
Binding binding = new Binding
{
Source = item,
Path = new PropertyPath("Value"),
Mode = BindingMode.TwoWay,
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
};
TextBox textBox = new TextBox { TextWrapping = TextWrapping.Wrap };
BindingOperations.SetBinding(textBox, TextBox.TextProperty, binding);
GridLexemesViewer.Children.Add(textBox);
Grid.SetColumn(textBox, CurrentSession.Languages.IndexOf(item.Language) + 1);
Grid.SetRow(textBox, index);
}
index++;
}
}
private void CreateRowsAndColumns()
{
int indexRow = 1;
int indexColumn = 1;
RowDefinition firstRowDefinition = new RowDefinition();
ColumnDefinition firstColumnDefinition = new ColumnDefinition { Width = GridLength.Auto };
GridLexemesViewer.ColumnDefinitions.Add(firstColumnDefinition);
GridLexemesViewer.RowDefinitions.Add(firstRowDefinition);
foreach (var key in CurrentSession.Lexemes.Keys)
{
RowDefinition rowDefinition = new RowDefinition();
GridLexemesViewer.RowDefinitions.Add(rowDefinition);
TextBlock textBlock = new TextBlock{Text = key};
GridLexemesViewer.Children.Add(textBlock);
Grid.SetRow(textBlock, indexRow);
indexRow++;
}
foreach (var language in CurrentSession.Languages)
{
ColumnDefinition columnDefinition = new ColumnDefinition { Width = new GridLength(1.0, GridUnitType.Star)};
GridLexemesViewer.ColumnDefinitions.Add(columnDefinition);
TextBlock textBlock = new TextBlock {Text = language};
GridLexemesViewer.Children.Add(textBlock);
Grid.SetRow(textBlock, 0);
Grid.SetColumn(textBlock, indexColumn);
indexColumn++;
}
}
This GIF shows how to reproduce bug
The problem is that you are calling CreateRowsAndColumns() each time but not removing the Rows and Columns from previous run. Using Grid.Clear() only deletes the children controls in the Grid, but the Grid.RowDefinitions and Grid.ColumnDefinitions stay intact.
To fix this, clear both definitions at the start of CreateRowsAndColumns():
GridLexemesViewer.RowDefinitions.Clear();
GridLexemesViewer.ColumnDefinitions.Clear();
However, definitely consider using the DataGrid control from the Windows Community Toolkit as it should have all the features you need and has better maintainability and performance then a custom Grid, especially for bigger data.
I would like to know how to disable ComboBox DropDown Button Programmatically. I had seen many similar subjects but all of these have a XAML solution.
By the way, if someone know how to disable all ComboBox control design and left visible only item template it can be helpful too.
UPDATE
its my XAML definition
<ComboBox Name="lang_ComboBox" SelectionChanged="LanguageSelection_ComboBox_SelectionChanged"/>
And there is how i use it:
String text = "dorf";
BitmapImage image = new BitmapImage(new Uri("http://img88.imageshack.us/img88/4351/butchermi4.png"));
lang_ComboBox.Width = 100;
lang_ComboBox.Height = 30;
Grid sp;
for (int i = 0; i < 5; i++)
{
ColumnDefinition gridCol1 = new ColumnDefinition();
gridCol1.Width = new GridLength(30.0);
ColumnDefinition gridCol2 = new ColumnDefinition();
gridCol2.Width = new GridLength(70.0);
sp = new Grid()
{
Width = 100,
Height = 30
};
Image im = new Image()
{
Source = image,
Width = 25,
Height = 25
};
Label la = new Label()
{
Content = text
};
sp.ColumnDefinitions.Add(gridCol1);
sp.ColumnDefinitions.Add(gridCol2);
Grid.SetColumn(im, 0);
Grid.SetColumn(la, 1);
sp.Children.Add(la);
sp.Children.Add(im);
lang_ComboBox.Items.Add(sp);
}
UPDATE 2
Hmmm I get it now, I use wrong word. It should be "Hide" control design and still can choose from a list. My bad sorry. But i know how i can solve it with Anatoliy Nokolaev's Code. To hide control design i use:
ToggleButton dropDownButton = GetFirstChildOfType<ToggleButton>(lang_ComboBox);
dropDownButton.Visibility = System.Windows.Visibility.Collapsed;
Unwanted behavior is now only that i cant show combobox dropdownmenu, but I'll invoke it programmatically by add on click event and should be good.
If there is any easiest way to do this tell me :).
To disable only the ToggleButton in ComboBox programmatically, you need to find this in the ComboBox control using VisualTreeHelper and assign a property IsEnabled to false, like this:
XAML
<Window x:Class="DisableComboBoxButton.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"
Loaded="Window_Loaded">
<StackPanel>
<ComboBox Name="comboBox"
Width="100"
Height="25"
SelectedIndex="0">
<ComboBoxItem>Test1</ComboBoxItem>
<ComboBoxItem>Test2</ComboBoxItem>
<ComboBoxItem>Test3</ComboBoxItem>
</ComboBox>
<ComboBox Name="AllComboBoxDisabled"
Width="100"
Height="25"
IsEnabled="False"
SelectedIndex="0">
<ComboBoxItem>Test1</ComboBoxItem>
<ComboBoxItem>Test2</ComboBoxItem>
<ComboBoxItem>Test3</ComboBoxItem>
</ComboBox>
</StackPanel>
</Window>
Code-behind
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
ToggleButton dropDownButton = GetFirstChildOfType<ToggleButton>(comboBox);
dropDownButton.IsEnabled = false;
}
public static T GetFirstChildOfType<T>(DependencyObject dependencyObject) where T : DependencyObject
{
if (dependencyObject == null)
{
return null;
}
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(dependencyObject); i++)
{
var child = VisualTreeHelper.GetChild(dependencyObject, i);
var result = (child as T) ?? GetFirstChildOfType<T>(child);
if (result != null)
{
return result;
}
}
return null;
}
}
Output
Notes
Always use GetFirstChildOfType() function only when the control will be fully loaded, otherwise it will not find it and give null. In this case, I put this code in the event Window_Loaded which says that all the controls of the Window successfully load.
Edit: another version
Not to say that this version is easier to implement, but it would be more correct and a bit easier to use.
So, we need a template for your ComboBox, because it allows access to elements that are within the control. Just like that, the ToggleButton can not be accessed from both the code and of XAML.
We create attached dependency property that will serve the current ComboBox another property, such as which will give access to our button Visibility.
Our property Visibility:
public static class ButtonExt
{
public static readonly DependencyProperty VisibilityProperty;
public static void SetVisibility(DependencyObject DepObject, Visibility value)
{
DepObject.SetValue(VisibilityProperty, value);
}
public static Visibility GetVisibility(DependencyObject DepObject)
{
return (Visibility)DepObject.GetValue(VisibilityProperty);
}
static ButtonExt()
{
PropertyMetadata VisibiltyPropertyMetadata = new PropertyMetadata(Visibility.Collapsed);
VisibilityProperty = DependencyProperty.RegisterAttached("Visibility",
typeof(Visibility),
typeof(ButtonExt),
VisibiltyPropertyMetadata);
}
}
Setter property in ComboBox template (skip version, full version see in project in App.xaml file):
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBox}">
<Grid>
<ToggleButton Name="ToggleButton"
Template="{StaticResource ComboBoxToggleButton}"
IsChecked="{Binding Path=IsDropDownOpen,
Mode=TwoWay,
RelativeSource={RelativeSource TemplatedParent}}"
Visibility="{TemplateBinding PropertiesExtension:ButtonExt.Visibility}" // <------ Here
Grid.Column="2"
Focusable="False"
ClickMode="Press" />
Now, we are setting this property like this:
<ComboBox Name="comboBox"
Style="{StaticResource ComboBoxBaseStyle}"
PropertiesExtension:ButtonExt.Visibility="Visible"
Width="100"
Height="30"
SelectedIndex="0">
<ComboBoxItem>Test1</ComboBoxItem>
<ComboBoxItem>Test2</ComboBoxItem>
<ComboBoxItem>Test3</ComboBoxItem>
</ComboBox>
or in code-behind via Click event handlers:
private void HideButton_Click(object sender, RoutedEventArgs e)
{
ButtonExt.SetVisibility(comboBox, Visibility.Hidden);
}
private void ShowButton_Click(object sender, RoutedEventArgs e)
{
ButtonExt.SetVisibility(comboBox, Visibility.Visible);
}
Full version of example project is here.
Try with this
Dispatcher.BeginInvoke(new Action(() =>
{
ToggleButton dropDownButton = GetFirstChildOfType<ToggleButton>(cboMedicos);
if (dropDownButton != null)
{
dropDownButton.IsEnabled = false;
}
}), System.Windows.Threading.DispatcherPriority.Render);
public static T GetFirstChildOfType<T>(DependencyObject dependencyObject) where T : DependencyObject
{
if (dependencyObject == null)
{
return null;
}
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(dependencyObject); i++)
{
var child = VisualTreeHelper.GetChild(dependencyObject, i);
var result = (child as T) ?? GetFirstChildOfType<T>(child);
if (result != null)
{
return result;
}
}
return null;
}
I have a WPF app that I'm testing which loads a XML and visualizes it in a usercontrol. Now the issue I'm having is that every time I load my user control the HorizontalAlignment is okay, but the VerticalAlignment doesn't adept to the height size of the usercontrol.
Anyone has an idea how to solve this?
MainWindow.xaml
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:UserControls="clr-namespace:RackBuildingTesT.UserControls" x:Class="RackBuildingTesT.MainWindow"
Title="MainWindow" Height="578" Width="758" SizeChanged="Window_SizeChanged_1">
<Grid>
<DockPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Border DockPanel.Dock="Top" BorderBrush="Black" BorderThickness="1">
<Grid>
<Label Content="Welke rack laden" HorizontalAlignment="Left" VerticalAlignment="Top"/>
<ComboBox x:Name="RackChooser" HorizontalAlignment="Left" Margin="100,0,0,0" VerticalAlignment="Top" Width="120" SelectionChanged="RackChooser_SelectionChanged"/>
</Grid>
</Border>
<Border DockPanel.Dock="Top" BorderBrush="Black" BorderThickness="1">
<Grid x:Name="RackGrid" Margin="0,0,0,0">
</Grid>
</Border>
</DockPanel>
</Grid>
MainWindow.xaml.cs
public MainWindow()
{
InitializeComponent();
LoadRackCombo();
}
private void LoadRackCombo()
{
var files = Directory.GetFiles(Properties.Settings.Default.FilePathXMLRack);
foreach (var item in files)
{
RackChooser.Items.Add(item);
}
}
private void RackChooser_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
this.RackGrid.Children.Clear();
this.Cursor = Cursors.Wait;
if (RackChooser.SelectedIndex == -1)
MessageBox.Show("Select a rack");
else
{
string rackFile = Convert.ToString(RackChooser.Items[RackChooser.SelectedIndex]);
UserControls.RackBuilder r = new UserControls.RackBuilder();
RackGrid.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
RackGrid.VerticalAlignment = System.Windows.VerticalAlignment.Stretch;
r.Width = RackGrid.Width;
r.Height = RackGrid.Height;
var _r = TRack.CreateFromXMLFile(rackFile, null);
r.set_Rack(_r);
RackGrid.Children.Add(r);
}
this.Cursor = Cursors.Arrow;
}
private void Window_SizeChanged_1(object sender, SizeChangedEventArgs e)
{
RackGrid.Width = this.Width;
RackGrid.Height = this.Height;
}
RackBuilder.xaml.cs (xaml page is standard WPF usercontrol)
public RackBuilder()
{
InitializeComponent();
}
public TRack fRack { get; set; }
public void set_Rack(TRack value)
{
this.fRack = value;
this.InvalidateVisual();
}
protected override void OnRender(DrawingContext drawingContext)
{
if (this.fRack != null)
{
var xScale = this.Width / this.fRack.Size.Width;
var yScale = this.Height / this.fRack.Size.Height;
var smallest = 0.0;
if (xScale < yScale)
smallest = xScale;
else
smallest = yScale;
foreach (var hole in this.fRack.HolePositions)
{
drawingContext.DrawEllipse(Brushes.Aquamarine, null, new Point(hole.Position.X * xScale, hole.Position.Y * yScale),
hole.Diameter * smallest * 0.5, hole.Diameter * smallest * 0.5);
}
}
}
Result
Instead of adding your Control to a Grid, use the ContentControl and add it to its Content-Property.
It also stretches its child automatically.
I fixed it with putting the MainWindow SizeToContent to WidthAndHeight.
i am building an application to show all the software installed in the computer, i already have all the buttons to show with the respective icon, but when i show them, the uniformgrid only shows the buttons that fit in to the window, i thought a scrollbar will show them, but i get to the end of the window and the buttons still missing! how can i show them all with a scrollbar?
Here is the XAML code:
<Window x:Class="apple.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow">
<Grid>
<DockPanel Name="dock">
<ScrollViewer VerticalScrollBarVisibility="Auto">
<UniformGrid Name="gridx" DockPanel.Dock="Top" Rows="7" Columns="7">
</UniformGrid>
</ScrollViewer>
</DockPanel>
</Grid>
</Window>
Here is the c# code:
namespace apple
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public string[] link = Directory.GetFiles(#"C:\ProgramData\Microsoft\Windows\Start Menu\Programs", "*.lnk", SearchOption.AllDirectories);
public MainWindow()
{
this.ResizeMode = ResizeMode.NoResize;
//this.WindowStyle = WindowStyle.None;
this.WindowState = WindowState.Maximized;
InitializeComponent();
masterGUI();
}
public void masterGUI()
{
gridx.Height = System.Windows.SystemParameters.PrimaryScreenHeight;
IconImage[] ico = null;
Bitmap[] img = null;
string[] list = null;
list = new string[link.Length];
ico = new Icon[link.Length];
img = new Bitmap[link.Length];
for (int n = 0; n < link.Length; n++)
{
ImageBrush ib = new ImageBrush();
System.Windows.Controls.Button newBtn = new Button();
list[n] = System.IO.Path.GetFileNameWithoutExtension(link[n]);
FileToImageIconConverter some = new FileToImageIconConverter(link[n]);
ImageSource imgSource = some.Icon;
ib.ImageSource = imgSource;
newBtn.Name = "a" + n;
newBtn.Background = ib;
newBtn.Content = list[n];
newBtn.Click += new RoutedEventHandler(newBtn_Click);
gridx.Children.Add(newBtn);
}
}
private void newBtn_Click(object sender, RoutedEventArgs e)
{
Button clicked = (Button)sender;
string test = null;
test = clicked.Name.Replace("a","0");
this.Close();
System.Diagnostics.Process.Start(link[Int32.Parse(test)]);
}
}
}
Remove the Grid and DockPanel and set either UniformGrid.Rows or UniformGrid.Columns, not both. All you need is Window, ScrollViewer, and UniformGrid:
<Window>
<ScrollViewer>
<UniformGrid Name="gridx" Columns="7"/>
</ScrollViewer>
</Window>
And to do it in a more idiomatic WPF fashion, you should have something like this:
<Window>
<ScrollViewer>
<ItemsControl ItemsSource="{Binding Programs}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="7"/>
You would then expose a Programs collection from your data source and would thus automatically generate an item for each installed program.