I have a slider in wpf and want the user , set the min and max value of it.
in xaml code :
<Slider x:Name="slider1" Width="34" Minimum="{Binding Path=Minval}" Value="10" Height="105" Margin="5,5,5,5" Maximum="{Binding Path=Maxval}"/>
<TextBox Height="23" HorizontalAlignment="Left" Margin="5,5,5,5" Name="minvaltxt" VerticalAlignment="Top" Width="120" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="5,5,5,5" Name="maxvaltxt" VerticalAlignment="Top" Width="120" />
<Button Content="Apply" Name="btn" Height="23" HorizontalAlignment="Left" Margin="5,5,5,5" VerticalAlignment="Top" Width="24" Click="btn_Click" />
in code behind :
private double maxval = 80;
public double Maxval
{
get { return maxval; }
set { value = maxval; }
}
private double minval = 5;
public double Minval
{
get { return minval; }
set { value = minval; }
}
private void btn_Click(object sender, RoutedEventArgs e)
{
minval= double.Parse(minvaltxt.Text);
maxval= double.Parse(maxvaltxt.Text);
slider1.Minimum = Minval
slider1.Maximum = Maxval;
}
but it does not update the min and max value of silder !
what is the problem ?
thanks for any help.
.
the question now edited.
thanks.
Have you set the DataContext for your view?
In Xaml you have used Maxcamdistance while the property name is Maxval in VM.
Implement INotifyPropertyChanged on your class and raise propertychanged for your property.
In button_click() set Properties not variables.
The problem is that you don't use dependency properties or INotifyPropertyChanged to inform the UI that the values of Minval and Maxval were changed. Have a look at my answer here: Bind boolean to visualstate
Thanks for all of lovely users who try to help .
Finaly I found the solution.
Infact , it did not need INotifyPropertyChanged or dependency properties !
The problem was about using 2 Windows Form Host in the same windows that causes one of
numericupdown return zero !
I do not khow why this accured but I used UserControl to overcome this problem.
User Control supports multiple Windows Form Host without any problem.
It seems that wpf windows has a limitation for hosting windows form.
Thanks alot.
Be Fresh.
Related
First time really using WPF - thought I'd have a go at remaking something I did a while back in Java.
I'm trying to bind the Text value of a TextBlock on a popup to something that gets set in the backend, so I can use one handler method to display any message on said popup.
I've been trying multiple different routes, such as fully binding it in the cs instead of XAML like so:
<--XAML-->
<Popup Margin="89,75,0,0" Name="verif_popup" HorizontalAlignment="Left" VerticalAlignment="Top" IsOpen="False" PopupAnimation="Slide" Placement="Center" Width="100" Height="100" Grid.Column="1">
<Popup.Effect>
<BlurEffect/>
</Popup.Effect>
<Canvas Background="Azure">
<TextBlock Name="VerifTextBlock"/>
</Canvas>
</Popup>
<--CS-->
private void SmallPopupHandler(string text)
{
Binding binding = new("Text")
{
Source = text
};
VerifTextBlock.SetBinding(TextBlock.TextProperty, binding);
verif_popup.IsOpen = true;
}
But it doesn't like the fact that the string isn't a TextBlock property, I sort of knew this wouldn't work but it seems the most logical to me having come from swing. There also doesn't seem to be a way for me to cast it to it and im not in the mood for making my own dependency property rn...
The next thing I tried was to bind the value to a field in the class, but I just got a stackoverflow error (haha nice)
<--XAML-->
<Popup Margin="89,75,0,0" Name="verif_popup" HorizontalAlignment="Left" VerticalAlignment="Top" IsOpen="False" PopupAnimation="Slide" Placement="Center" Width="100" Height="100" Grid.Column="1">
<Popup.Effect>
<BlurEffect/>
</Popup.Effect>
<Canvas Background="Azure">
<Canvas.DataContext>
<local:MainWindow/>
</Canvas.DataContext>
<TextBlock Name="VerifTextBlock" Text="{Binding Popup_message}"/>
</Canvas>
</Popup>
<--CS-->
public partial class MainWindow : Window
{
public string? Popup_message { get; set; }
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
}
I also tried making an interfacing class of sorts to see if that would work around the stackoverflow error (haha) but as im sure you could have guessed by now, that didn't work either...
Kinda pulling my hair out so any help would be greatly appreciated!
Thanks in advance!
You could just set the Text property of the VerifTextBlock directly as suggested by #Clemens:
private void SmallPopupHandler(string text)
{
VerifTextBlock.Text = text;
verif_popup.IsOpen = true;
}
If you really do want to use a binding for whatever reason, then remove the binding path. This should work:
private void SmallPopupHandler(string text)
{
Binding binding = new()
{
Source = text
};
VerifTextBlock.SetBinding(TextBlock.TextProperty, binding);
verif_popup.IsOpen = true;
}
I'm looking for a way to retrieve and force user to enter an int value in a WPF application (developed in C#).
What is the best way to do it ? I've seen "TextBox" can do the Job with value parsing, but i wonder if there is a better way to do it with another WPF control (other than a TextBox) to help user to do so more easily (with up or down button to increment or decrement for example) ?
Goal is to simplify user experience by "guiding" him during "value" selection
Just for you, I've quickly wrote this. This isn't the most efficient way of doing this also you can implement more validations like for decimal numbers or non-negative numbers. Also you can make TexBox IsReadOnly = true to make sure user don't input any non-numeric values.
You can do a lot of the things ! this is just to give you an idea.
XAML
<StackPanel Orientation="Horizontal" Width="200" VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBox x:Name="NumberBox" VerticalAlignment="Center" Width="120" Text="0"></TextBox>
<StackPanel Orientation="Vertical" VerticalAlignment="Center"
Margin="2 0 0 0" Spacing="1">
<Button x:Name="UpBtn" Width="50" Height="25" Click="IncrementDecrement">▲</Button>
<Button x:Name="DownBtn" Width="50" Height="25" Click="IncrementDecrement">▼</Button>
</StackPanel>
</StackPanel>
Back-End Code (non MVVM WAY)
private void IncrementDecrement(object sender, RoutedEventArgs e)
{
var senderBtn = sender as Button;
var value = NumberBox.Text.Trim();
if (string.IsNullOrEmpty(value))
{
value = 0.ToString();
}
bool success = Int32.TryParse(value, out var number);
if (!success)
{
// show error
return;
}
NumberBox.Text = senderBtn.Name == "UpBtn" ? (++number).ToString() : (--number).ToString();
}
Result
I would like to binding as below:
A (in View) <---> B (in View) <----> C (MyData)
Binding A-B : Two way
Binding B-C : One way
Xaml
<Slider x:Name="slider" Minimum="0" Maximum="100" Value="{Binding Path=Text, ElementName=textBox, Mode=TwoWay}"/>
<TextBox x:Name="textBox" Text="{Binding Path=MyValue, Mode=OneWay}"/>
<Button x:Name="button" Content="Button" Click="button_Click"/>
Code Behind:
public int MyValue
{
get { return m_value; }
set
{
m_value = value;
NotifyPropertyChanged("MyValue");
}
}
...
private void button_Click(object sender, RoutedEventArgs e)
{
MyValue = 10;
}
I expect that when I click on button, the value of text box and slider bar will be updated.
However, nothing happen.
Please help me to solve this problem.
Thank in advance.
What you are trying to do is wrong in the architecture, that's why i would suggest you to take a look at some documentation about MVVM
such as:
https://www.codeproject.com/Articles/819294/WPF-MVVM-step-by-step-Basics-to-Advance-Level
or instead of considering just PRISM there are some more that are powerful but more approchable and easier such as MvvmLight:
http://www.dotnetcurry.com/wpf/1037/mvvm-light-wpf-model-view-viewmodel
Hope having been useful
XAML code:
<TextBlock Text="Country" Foreground="white" TextAlignment="Right" Grid.Row="2" Grid.Column="0" />
<TextBox
x:Name="txtCountries"
Grid.Row="2"
Grid.Column="1"
Grid.ColumnSpan="2"
HorizontalAlignment="Stretch"
Margin="2, 2, 2, 2"
Text="{Binding PhysicalDeliveryParameters.Countries, Converter={StaticResource EnumerableToTextConverter}, ConverterParameter='...'}"
IsReadOnly="True">
</TextBox>
<Button
Grid.Row="2"
Grid.Column="3"
Content="..."
HorizontalAlignment="Left"
Tag="Countries"
Click="ButtonBase_OnClick" />
C# code :
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
PhysicalDeliveryParametersViewModel pvm = GetViewModel();
GenericObservableCollection<SelectableItem> items = pvm.Countries;
PhysicalDeliveryParametersDlg dlg = new PhysicalDeliveryParametersDlg(items);
dlg.Closed += (o, args) =>
{
BindingExpression binding = txtCountries.GetBindingExpression(TextBox.TextProperty);
if(null != binding)
binding.UpdateSource();
};
dlg.ShowDialog();
}
When I click on the button, the ButtonBase_OnClick() method executes : a dialog appears (PhysicalDeliveryParametersDlg class) and I choose some values. The binded data (PhysicalDeliveryParameters.Countries, which is an ObservableCollection) is updated, but not the Text property of my TextBox... Did I do something wrong ?
PS : I'm not sure I use the best method to create a modal window in Silverlight, could you give me some advice ?
It looks like the problem is that PropertyChanged never gets raised on the "Countries" property, so the view doesn't know it needs to update. (Actually, it probably wouldn't help to raise "PropertyChanged" in this case -- since the object reference has not changed, I believe the runtime would ignore it.)
I would just add another property "CountriesString" or similar:
Text="{Binding PhysicalDeliveryParameters.CountriesString}"
Update the property whenever is appropriate:
dlg.Closed += (o, args) =>
{
pvm.CountriesString = string.Join(", ", pvm.Countries);
};
I cannot find any examples to make me understand how and if I can change the databind in c# at the click of a button on, in my case a toggleswitch, Basically I have 32 buttons in my app and those 32 buttons act the same but need different text with-in them depending on some toggle switches they are currently databinded so the text can be saved and retrieved from local storage but what values it gets depends on the state of these toggle switches.
So I currently have :
<Button x:Name="_ovButton1" Content="{Binding Source={StaticResource AppSettings}, Path=ovName1_1Value, Mode=TwoWay}" Margin="2,0,250,0" VerticalAlignment="Top" FontSize="14" Height="72" FontWeight="Bold" MouseLeftButtonUp="_ovButton1_MouseLeftButtonUp" MouseLeftButtonDown="_ovButton1_MouseLeftButtonDown" ClickMode="Hover" Hold="_ovButton1_Hold"/>
and I want when a user changes the state of a toggleswitch to change the
{StaticResource AppSettings}, Path=ovName1_1Value, Mode=TwoWay}
to for example:
{StaticResource AppSettings}, Path=ovName1_2Value, Mode=TwoWay}
but I cannot find any example that shows how to do that in c#
what code do I need to do that?
You can specify the target of databinding in code like this:
MyData myDataObject = new MyData(DateTime.Now);
Binding myBinding = new Binding("MyDataProperty");
myBinding.Source = myDataObject;
myText.SetBinding(TextBlock.TextProperty, myBinding);
See more at http://msdn.microsoft.com/en-us/library/ms742863.aspx
-- Edit Note I don't have access to a WP8 Emulator to test this ---
In the view model it looks like this:
public List<string> Members
{
get { return _Members; }
set { _Members = value; OnPropertyChanged(); }
}
public MainVM()
{
// Simulate Asychronous access, such as to a db.
Task.Run(() =>
{
Thread.Sleep(2000);
Members = new List<string>() {"Alpha", "Beta", "Gamma", "Omega"};
});
}
The code behind on the main page sets the datacontext (shared with all the child controls) as such:
public MainWindow()
{
InitializeComponent();
// Set the windows data context so all controls can have it.
DataContext = new MainVM();
}
The Mainpage Xaml to bind to members is like this
<Button Height="30"
Width="80"
Margin="10"
DataContext="{Binding Members}"
Content="{Binding Path=[0] }" />
<Button Height="30"
Width="80"
Margin="10"
DataContext="{Binding Members}"
Content="{Binding Path=[1] }" />
<Button Height="30"
Width="80"
Margin="10"
DataContext="{Binding Members}"
Content="{Binding Path=[2] }" />
<Button Height="30"
Width="80"
Margin="10"
DataContext="{Binding Members}"
Content="{Binding Path=[3] }" />
The result is this visually:
I based this on my blog article Xaml: ViewModel Main Page Instantiation and Loading Strategy for Easier Binding for more info and a fuller example.
I think your best bet is going to be to use a collection of strings and bind to that collection. You can either change the collection when a toggle is switched, or keep 6 collections and bind to the collection that is for the toggle.
Xaml:
<ItemsControl x:Name="Buttons" ItemsSource="{Binding ButtonTextCollection}">
<ItemsControl.ItemsPanel>
<toolkit:WrapPanel/>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Width="100" Height="70" Content="{Binding}" Click="OnButtonClick"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Your code-behind would have the event handler for your button click
private void OnButtonClick(object sender, RoutedEventArgs e)
{
var text = ((Button) sender).Content.ToString();
// Send the text
}
Your ViewModel would hold the ButtonTextCollection property and would change based on the toggle.
public ICollection<string> ButtonTextCollection
{
get { return _buttonTextCollection; }
set
{
_buttonTextCollection = value;
OnPropertyChanged("ButtonTextCollection");
}
}
When you want to change the text, you would change the ButtonTextCollection
public void ChangeButtonText()
{
ButtonTextCollection = new Collection<string> {"A", "B",...};
}