I searched a lot for the solution to this, but can't seem to figure it out. (Just saying, this will be a long post)
Preface: This is NOT MVVM
Problem: I have a progress bar. I am currently trying to bind a public double to it from within the xaml's .cs file. However, whenever I use value's bind function, it never works, resulting in iNotifyPropertyChanged not working, etc. etc....
The variable it is bound to serves the purpose of updating the progress bar value. The way that is completed is by setting the value in a separate for loop in another method/class. The value is set by a simple equation. 100 divided by the length of a list, multiplied by the for loops counter. This gives us a real number that can be put into the progress bar value. (code below)
Binder.daWindow.progUpdate = ((100.00 / databaseTables.Length) * dbTIndex);
I know this can be completed by threading (or whatever), but I would appreciate answers specifically for how this might be done by binding (unless it's impossible, then forget what I just said).
XAML:
<Window x:Name="DateWindow1" x:Class="WpfApp1.DateWindow"
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"
xmlns:Main="using:DateWindow"
mc:Ignorable="d"
Title="Change Dates" Height="232.667" Width="462" Background="#FF2B2B2B" ResizeMode="NoResize">
<Grid>
<TextBox x:Name="DayChangeTextBox" HorizontalAlignment="Left" Height="30" Margin="176,45,0,0" TextWrapping="Wrap" Text="##" VerticalAlignment="Top" Width="58" FontSize="14" TextAlignment="Center" AcceptsReturn="False" AcceptsTab="False" GotFocus="DayChangeTextBox_GotFocus" LostFocus="DayChangeTextBox_LostFocus" BorderThickness="1" BorderBrush="Black" OpacityMask="Black" Background="#FFFDFDFD"/>
<Label Content="Days" HorizontalAlignment="Left" Margin="239,45,0,0" VerticalAlignment="Top" Width="42" FontSize="14" FontFamily="Microsoft YaHei UI" Height="30" Foreground="White"/>
<Label Content="Move Dates Forward:" HorizontalAlignment="Left" Margin="23,45,0,0" VerticalAlignment="Top" Width="144" FontSize="14" FontFamily="Microsoft JhengHei UI Light" Height="30" Foreground="White"/>
<Button x:Name="ChangeDatesButton" Content="Change Dates" HorizontalAlignment="Left" Margin="303,45,0,0" VerticalAlignment="Top" Width="143" Height="30" BorderThickness="1,1,2,3" BorderBrush="#FF474747" Click="ChangeDatesButton_Click" FontFamily="Microsoft YaHei UI" Background="#FFE6E6E6"/>
<Label x:Name="serverLabel" Content="Label" HorizontalAlignment="Left" Margin="10,73,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.5,0.5" Width="5" Height="15" Visibility="Hidden"/>
<Label x:Name="databaseLabel" Content="Label" HorizontalAlignment="Left" Margin="20,73,0,0" VerticalAlignment="Top" Width="3" Visibility="Hidden" Height="15"/>
<Button x:Name="RevertToDefaultButton" Content="Revert to Backup" Margin="23,164,0,0" VerticalAlignment="Top" Height="30" Background="#FFE6E6E6" BorderBrush="#FF474747" BorderThickness="1,1,2,3" Click="RevertToDefaultButton_Click" FontFamily="Microsoft JhengHei UI" HorizontalAlignment="Left" Width="143"/>
<Button x:Name="OverwriteDefaultButton" Content="Backup Database" Margin="23,128,0,0" VerticalAlignment="Top" Height="30" BorderBrush="#FF474747" BorderThickness="1,1,2,3" Click="OverwriteDefaultButton_Click" FontFamily="Microsoft JhengHei UI" HorizontalAlignment="Left" Width="143" Background="#FFE6E6E6" />
<Button x:Name="CloseButton" Content="Close" Margin="0,164,10,0" VerticalAlignment="Top" Height="30" BorderBrush="#FF474747" BorderThickness="1,1,2,3" FontFamily="Microsoft JhengHei UI" Width="60" Click="CloseButton_Click" HorizontalAlignment="Right" Background="#FFE6E6E6" />
<Label x:Name="RevertBackupLabel" Content="Backup or Revert Database:" HorizontalAlignment="Left" Margin="12,93,0,0" VerticalAlignment="Top" Foreground="White" FontFamily="Microsoft JhengHei UI" FontWeight="Bold" FontSize="16"/>
<Label x:Name="DatesLabel" Content="Change Dates in Database:" Margin="12,10,0,0" Foreground="White" FontFamily="Microsoft JhengHei UI" FontWeight="Bold" FontSize="16" HorizontalAlignment="Left" Width="216" Height="30" VerticalAlignment="Top"/>
<ProgressBar HorizontalAlignment="Left" Height="13" Margin="303,80,0,0" VerticalAlignment="Top" Width="143" Name="pbStatus" Value="{Binding local.progUpdate, UpdateSourceTrigger=PropertyChanged}" Maximum="{Binding mx}" Minimum="{Binding mn}" LargeChange="0.01"/>
</Grid>
XAML CS Portion:
public static class Binder
{
public static DateWindow daWindow;
}
public partial class DateWindow : Window, INotifyPropertyChanged
{
private double _progUpdate;
public double progUpdate
{
get { return _progUpdate; }
set
{
_progUpdate = value;
if (PropertyChanged != null)
{
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(nameof(progUpdate)));
}
}
}
public double mx = 100;
public double mn = 0;
public event PropertyChangedEventHandler PropertyChanged;
public DateWindow()
{
InitializeComponent();
Binder.daWindow = this;
ChangeDateInDatabase ChangeDate = new ChangeDateInDatabase();
progUpdate = 25; // This is there so we can test the variable without going through the whole program.
}
private void ChangeDatesButton_Click(object sender, RoutedEventArgs e)
{
ChangeDateInDatabase ChangeDate = new ChangeDateInDatabase();
var result = MessageBox.Show("Are you sure you would like to change dates for " + Globals.selectedDatabase + " from server " + Globals.main.ServerComboBox.Text + "?", "Change Dates?", MessageBoxButton.YesNo, MessageBoxImage.Exclamation);
if (Globals.main.ServerComboBox.Text != "" && Globals.selectedDatabase != "" && FindDatabaseAndServer.Connector(Globals.main.ServerComboBox.Text, Globals.selectedDatabase) && result == MessageBoxResult.Yes)
{
try
{
long.Parse(DayChangeTextBox.Text);
ChangeDate.ChangeDates(this);
//ChangeDateInDatabase.ChangeDates(this);
}
catch
{
MessageBox.Show($"Invalid number {DayChangeTextBox.Text}, please enter a valid number.", "ERROR", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
}
(CLICK function serves the purpose of calling a method for the program. Inside the method, its main loop, which determines the methods completion, contains the variable desired to be bound with a defining equation for its value)
Method Containing Said Loop:
for (int dbTIndex = 0; dbTIndex < databaseTables.Length; dbTIndex++)
{
string[] dateColumns = new string[0];
string columnSelectQuery = "SELECT DATA_TYPE, COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '" + databaseTables[dbTIndex].ToString() + "' AND COLUMN_NAME LIKE '_%'";
using (SqlConnection connection2 = new SqlConnection(connectionString))
{
SqlCommand command2 = new SqlCommand(columnSelectQuery, connection2);
connection2.Open();
SqlDataReader reader2 = command2.ExecuteReader();
int y = 0;
while (reader2.Read())
{
if (reader2[0].ToString() == "datetime")
{
Array.Resize(ref dateColumns, dateColumns.Length + 1);
dateColumns[y] = reader2[1].ToString();
y++;
}
}
}
for (var dtColIndex = 0; dtColIndex < dateColumns.Length; dtColIndex++)
{
string addDatesQuery = "UPDATE " + databaseTables[dbTIndex] + " SET " + dateColumns[dtColIndex] + " = DATEADD(dd," + Convert.ToInt32(date.DayChangeTextBox.Text) + "," + dateColumns[dtColIndex] + ") WHERE " + dateColumns[dtColIndex] + " IS NOT NULL";
using (SqlConnection connection3 = new SqlConnection(connectionString))
{
SqlCommand command3 = new SqlCommand(addDatesQuery, connection3);
connection3.Open();
command3.ExecuteNonQuery();
}
}
//vvvvv VARIABLE THAT NEEDS TO BE BOUND vvvvvvv
Binder.daWindow.progUpdate = ((100.00 / databaseTables.Length) * dbTIndex);
}
(There is obviously more code to this part, which I can provide if needed)
Thanks in advance!
EDIT:
For the XAML, local.progUpdate is not the only thing I have tried. I've done path, progUpdate by itself, etc.
Your ProgressBar's first binding makes no sense: {Binding local.progUpdate, UpdateSourceTrigger=PropertyChanged}. You're not specifying a source, and there's no DataContext assigned anywhere, so the binding won't evaluate to anything because the path is meaningless. Because the property is on the window itself, you can just assign the window's data context to itself.
// DateWindow.xaml.cs
public DateWindow()
{
InitializeComponent();
DataContext = this;
...
}
<!-- DateWindow.xaml -->
<ProgressBar Value="{Binding progUpdate, Mode=OneWay}" ... />
Your other bindings will require mx and mn to be properties rather than fields.
I try to implement a video in WPF. The video is visible in Visual Studio (so I think the path is correct) but isn't visible (I also hear nothing) while I run the program. I have 1 MediaElement to implement the video and 3 Buttons (Play, Pause, Mute) below. The Build-Property of the video is "Resource".
XAML-Code:
<StackPanel HorizontalAlignment="Center" Width="340" Height="300" Margin="281,63,0,0" VerticalAlignment="Center">
<MediaElement Name="myMedia" Source="testvideo.wmv" LoadedBehavior="Manual" Width="320" Height="240" />
<StackPanel Orientation="Horizontal" Margin="0, 10, 0, 0">
<Button Content="Play" Margin="0, 0, 10, 0" Padding="5" Click="mediaPlay"/>
<Button Content="Pause" Margin="0, 0, 10, 0" Padding="5" Click="mediaPause"/>
<Button x:Name="muteButt" Content="Mute" Padding="5" Click="mediaMute"/>
</StackPanel>
</StackPanel>
Code Behind:
public MainWindow()
{
InitializeComponent();
myMedia.Volume = 100;
myMedia.Play();
myMedia.Position = new TimeSpan(0, 0, 5); // first frame 5 seconds
}
void mediaPlay(Object sender, EventArgs e)
{
myMedia.Play();
}
void mediaPause(Object sender, EventArgs e)
{
myMedia.Pause();
}
void mediaMute(Object sender, EventArgs e)
{
if (myMedia.Volume == 100)
{
myMedia.Volume = 0;
muteButt.Content = "Listen";
}
else
{
myMedia.Volume = 100;
muteButt.Content = "Mute";
}
}
I found my problem:
I had to set the property "Source" of the MediaElement in the code behind again. I don't know why, but now it works!
on click event ,I have return adding of menu items to contextmenu.but on clicking more than once it keeps adding the menu items to the contextmenu. Here the below code am using for it.
<StackPanel Grid.Row="13" Orientation="Horizontal" FlowDirection="LeftToRight">
<Button Name="btnMobile" Content="Home" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0 0 20 0" Width="70"></Button>
<!--<extToolkit:DropDownButton x:Name="ddBtnMobile" VerticalAlignment="Top" Width="30" HorizontalAlignment="Right" Margin="0 0 30 0" Height="20"/>-->
<Button HorizontalAlignment="Left" Name="ddBtnMobile" Width="30" Click="OnddBtnMobileClick" Margin="0,0,0,5" >
<Button.Content>
<Path x:Name="btnArrow3" Margin="4" VerticalAlignment="Center" Width="10" Fill="#FF527DB5" Stretch="Uniform" HorizontalAlignment="Right" Data="F1 M 301.14,-189.041L 311.57,-189.041L 306.355,-182.942L 301.14,-189.041 Z "/>
</Button.Content>
<Button.ContextMenu>
<ContextMenu Name="cMenu">
</ContextMenu>
</Button.ContextMenu>
</Button>
</StackPanel>
code am using is below
private void OnddBtnMobileClick(object sender, RoutedEventArgs e)
{
mnItem = new MenuItem();
mnItem.Header ="B1";
cMenu.Items.Add(mnItem);
mnItem = new MenuItem();
mnItem.Header ="A1";
cMenu.Items.Add(mnItem);
mnItem = new MenuItem();
mnItem.Header="B 2";
cMenu.Items.Add(mnItem);
cMenu.AddHandler(MenuItem.ClickEvent, new RoutedEventHandler(OnMenuItemClick));
}
private void OnMenuItemClick(object sender, RoutedEventArgs e)
{
RoutedEventArgs args = e as RoutedEventArgs;
MenuItem item = args.OriginalSource as MenuItem;
string header = item.Header.ToString();
if (header == "Business")
{
btnMobile.Content = header;
}
else if (header == "Assistant")
{
btnMobile.Content = header;
}
}
how to solve my issue.. Is there any better way of writing the above logic. i.e., adding menu items of context menu at run time.
add a boolean data member which will check if the sub menu's were already added
private void OnddBtnMobileClick(object sender, RoutedEventArgs e)
{
if(alreadyAdded == true)
return;
alreadyAdded = true;
mnItem = new MenuItem();
mnItem.Header ="B1";
cMenu.Items.Add(mnItem);
mnItem = new MenuItem();
mnItem.Header ="A1";
cMenu.Items.Add(mnItem);
mnItem = new MenuItem();
mnItem.Header="B 2";
cMenu.Items.Add(mnItem);
cMenu.AddHandler(MenuItem.ClickEvent, new RoutedEventHandler(OnMenuItemClick));
}
Add the following code in the button click event's starting.
cMenu = new cMenu();
Thats you need to create a new instance.
Thanks,
I have a DataGrid that LayoutTransform is Binded to a Slider like that:
<DataGrid.LayoutTransform>
<ScaleTransform
ScaleX="{Binding ElementName=MySlider, Path=Value}"
ScaleY="{Binding ElementName=MySlider, Path=Value}" />
</DataGrid.LayoutTransform>
</DataGrid>
<Slider x:Name="MySlider"
Minimum="0.3"
Maximum="2.0"
SmallChange="0.1"
LargeChange="0.1"
Value="1.0"
IsSnapToTickEnabled="True"
TickFrequency="0.1"
TickPlacement="TopLeft"
VerticalAlignment="Bottom"
HorizontalAlignment="Right"
Width="200"
Margin="0,0,61,0" />
<TextBlock Name="Lstate"
Text="{Binding ElementName=MySlider, Path=Value, StringFormat={}{0:P0}}"
VerticalAlignment="Bottom"
HorizontalAlignment="Right"
Width="50" Height="20"
Margin="0,0,0,1" />
Now, in the Code I have the PreviewMouseWheel event with the following Code:
bool handle = (Keyboard.Modifiers & ModifierKeys.Control) > 0;
if (!handle)
return;
double value;
if (e.Delta > 0)
value = 0.1;
else
value = -0.1;
MySlider.Value += value;
And my question is: How to scroll to the actual Mouse Position like AutoCad or some other programs?
Thanks
Sorry for my bad english...
I have a very very good solution now:
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Standard"
EnableColumnVirtualization="False"
EnableRowVirtualization="True"
ScrollViewer.CanContentScroll="True"
private void Data_OnPreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
// Scroll to Zoom
if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
{
// Prevent scroll
e.Handled = true;
var scrollview = FindVisualChild<ScrollViewer>(Data);
if (scrollview != null)
{
// The "+20" are there to account for the scrollbars... i think. Not perfectly accurate.
var relativeMiddle = new Point((Data.ActualWidth + 20) / 2 + (Mouse.GetPosition(Data).X - Data.ActualWidth / 2), (Data.ActualHeight + 20) / 2 + (Mouse.GetPosition(Data).Y - Data.ActualHeight / 2));
var oldLocation = Data.LayoutTransform.Transform(Data.PointFromScreen(relativeMiddle));
// Zoom
MySlider.Value += (e.Delta > 0) ? MySlider.TickFrequency : -MySlider.TickFrequency;
// Scroll
var newLocation = Data.LayoutTransform.Transform(Data.PointFromScreen(relativeMiddle));
// Calculate offset
var shift = newLocation - oldLocation;
if (scrollview.CanContentScroll)
{
// Scroll to the offset (Item)
scrollview.ScrollToVerticalOffset(scrollview.VerticalOffset + shift.Y / scrollview.ViewportHeight);
}
else
{
// Device independent Pixels
scrollview.ScrollToVerticalOffset(scrollview.VerticalOffset + shift.Y);
}
// Device independent Pixels
scrollview.ScrollToHorizontalOffset(scrollview.HorizontalOffset + shift.X);
}
}
}
It zooms to the Mouse Position on the Datagrid with and without virtualization.
I am attempting to scale an InkCanvas's contents (Strokes) to fit a fixed page size for printing. I want to essentially crop out all of the surrounding whitespace from the InkCanvas, and scale up the Strokes to fit the page while maintaining aspect ratio.
In the handler below the markup, you can see that I am changing the dimensions of the grid that starts at 800x300, and I'm making it 425x550, half of the size of a printable page.
markup:
<Grid>
<Button Height="100" Width="100" HorizontalAlignment="Left" PreviewMouseLeftButtonDown="Button_PreviewMouseLeftButtonDown_1" />
<Grid Width="1200" Height="1400" Background="Aquamarine" HorizontalAlignment="Right" VerticalAlignment="Top">
<Grid Background="Red" x:Name="grid" Width="800" Height="300">
<Viewbox x:Name="vb" Width="800" Height="300" Stretch="Fill" StretchDirection="Both">
<InkCanvas Width="500" Height="500" Background="Transparent" IsEnabled="True"/>
</Viewbox>
</Grid >
</Grid>
</Grid>
codebehind file:
bool b = true;
private void Button_PreviewMouseLeftButtonDown_1(object sender, MouseButtonEventArgs e)
{
if (b)
{
//I toyed with using Uniform, UniformToFill, and Fill
vb.Stretch = Stretch.Fill;
grid.Width = 425;
grid.Height = 550;
//scale viewbox down until it fits horizontally
var scaleX = grid.Width / vb.Width;
vb.Width *= scaleX;
vb.Height *= scaleX;
//if constraining it to the width made it larger than it needed to be vertically, scale it down
if (vb.Height > grid.Height)
{
var scaleY = grid.Height / vb.Height;
vb.Width *= scaleY;
vb.Height *= scaleY;
}
b = false;
}
else
{
//reset it back to what it was
vb.Stretch = Stretch.Fill;
grid.Width = 800;
grid.Height = 300;
vb.Width = grid.Width;
vb.Height = grid.Height;
b = true;
}