|
Slacker007 wrote: Not sure why you would not use Visual Studio Community Edition to manage/edit your WPF files and projects.
Perhaps Mike is secretly part of a large, enterprise development team.
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
What I'm looking for is a control I can slip into my app. Guess I didn't make that plain.
The less you need, the more you have.
Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?
JaxCoder.com
|
|
|
|
|
Sorry, Mike. I did not notice.
|
|
|
|
|
Looks like the SmithHtmlEditor project has moved to GitHub:
GitHub - adambarath/SmithHtmlEditor: The source code is about html editor usage in WPF application.[^]
It doesn't seem to have much detail there, and is still pointing to the (now defunct) CodePlex archive for more information. But the GitHub version seems to have been updated more recently.
There don't seem to be a huge number of other options - there's this one[^] from 2015, and this one[^], also from 2015, but beyond that Google is only suggesting commercial products.
I've not tried it, but you might have better luck embedding a WebView2[^] control and using a Javascript HTML editor.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Thanks Richard,
I considered the CodeProject one but settled on the smithhtmleditor. Seems to be working Ok, a little quirky with fonts but other than that fairly easy to use. All I need is some basic editing for keeping notes in the app I'm working on.
The less you need, the more you have.
Even a blind squirrel gets a nut...occasionally.
JaxCoder.com
|
|
|
|
|
I'm working on a WPF app that we now want to have a 'Test Mode'.
Right now, I have an 'IsTestMode' property in the app.config. If I set it to True, then the login window's border is red, and there's a red TEST MODE banner across the top of the main window. The Test Mode copy is installed in a different location then the production copy.
In the code behind of the Main Window I have:
Uri iconUri = null;
if (AppCore.IsTestMode)
{
iconUri = new Uri("my_test.ico", UriKind.Relative);
}
else
{
iconUri = new Uri("my.ico", UriKind.Relative);
}
this.Icon = BitmapFrame.Create(iconUri);
This changes the Taskbar Icon, not the desktop icon
This all works fine.
Now I want to add an installer project, but I'm stuck on how to make the Test Mode changes during installation. I'd like to do the following during installation and not let the user change them:
- Set the installation location
- Set the IsTestMode setting
- Change the desktop icon.
Can anyone shed some light on how to do this?
Thanks
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
modified 19-Jul-21 15:14pm.
|
|
|
|
|
I have a user control with a custom Routed Event. I'm trying to pass event args:
public class NavigationViewFilterEventArgs : RoutedEventArgs
{
public List<LookupEntity> StatusFilters { get; private set; }
public List<LookupEntity> FilterItems { get; private set; }
public NavigationViewFilterEventArgs(RoutedEvent e, List<LookupEntity> statusFilters, List<LookupEntity> filterItems) :
base(e)
{
StatusFilters = statusFilters;
FilterItems = filterItems;
}
}
Here's the UserControl code behind:
public static readonly RoutedEvent FilterExecutedEvent =
EventManager.RegisterRoutedEvent("FilterExecuted",
RoutingStrategy.Bubble,
typeof(RoutedEventHandler),
typeof(NavigationView));
public event RoutedEventHandler FilterExecuted
{
add { AddHandler(FilterExecutedEvent, value); }
remove { RemoveHandler(FilterExecutedEvent, value); }
}
private void RaiseFilterExecutedEvent()
{
var args = new NavigationViewFilterEventArgs(FilterExecutedEvent, StatusFilters, FilterItems);
RaiseEvent(args);
}
The control is on the Main Window:
<ctrls:NavigationView Grid.Row="7"
Caption="Companies"
StatusFilters="{Binding DataContext.CompanyStatusFilterItems,
ElementName=window, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="FilterExecuted">
<i:InvokeCommandAction Command="{Binding DataContext.CompanyFilterExecutedEventCommand,
ElementName=window}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ctrls:NavigationView>
And finally the handler in the Main Window view model:
private ICommand _CompanyFilterExecutedEventCommand;
public ICommand CompanyFilterExecutedEventCommand
{
get
{
if (_CompanyFilterExecutedEventCommand == null)
_CompanyFilterExecutedEventCommand = new RelayCommand<NavigationViewFilterEventArgs>(p => CompanyFilterExecutedEventExecuted(p), p => CompanyFilterExecutedEventCanExecute());
return _CompanyFilterExecutedEventCommand;
}
}
private bool CompanyFilterExecutedEventCanExecute()
{
return true;
}
private void CompanyFilterExecutedEventExecuted(NavigationViewFilterEventArgs args)
{
}
When I run this and click the button, the event reaches the Main Window VM's CompanyFilterExecutedEventExecuted method, but the param is always null.
I could use some help here.
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
|
I want to change the combobox's backgound but when set the default background it doesn't change, I want to change the background color in the code behind, thank!
|
|
|
|
|
Hi!
Sorry for weird subject but was a bit unsure on what to call it.
Anyway, I have a WPF-form where I have some items below a textbox. I want the textbox to fill up the grid above the bottom controls but leave space for them.
<Window x:Class="SMS_Sender_3._0.MainWindow"
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:SMS_Sender_3._0"
mc:Ignorable="d"
Title="SMS Sender 3.0" Height="350" Width="525">
<Grid>
<Border Margin="8">
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Phone:" />
<TextBox Grid.Column="1" />
</Grid>
<TextBlock Text="Message:" />
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="225" />
</Grid.RowDefinitions>
<TextBox Grid.Column="1" />
</Grid>
<Grid Margin="0,3,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="150" />
<ColumnDefinition Width="60" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Mall:" />
<ComboBox Grid.Column="1" />
<TextBlock Margin="5,0,0,0" Grid.Column="2" Text="0/160(1)" />
<Button Grid.Column="3" HorizontalAlignment="Right" Content="_Send" Width="100" />
</Grid>
<Grid Margin="0,3,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Type:" />
<ComboBox Grid.Column="1" HorizontalAlignment="Left" Width="150" />
</Grid>
</StackPanel>
</Border>
</Grid>
</Window>
As it is now, the textbox will change it width but not it's height, due to it being set to 225 in the grid definition. However, I am unsure how to set the grid so that it will take up the space but leave the bottom controls visible. Basically I want it to be as it is now but able to resize.
I am thankfull for any suggestions.
Have a nice day!
I am using JetBrains Rider!
|
|
|
|
|
|
When you put Grids in a StackPanel, the Grids "lose" their "star" (*) qualities since StackPanel do not fill available space.
You should put your Grids in a parent Grid instead of a StackPanel (if you want to make the most of "stretching").
I typically start everything with "*" or Auto; only afterwards do I (rarely) touch up with explicit widths or heights.
It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it.
― Confucian Analects: Rules of Confucius about his food
|
|
|
|
|
The purpose of this code is open image file in a page and display it in another page.
I had tried set ViewModel by using Singleton Pattern, but it didn't work....
If I integrate to one View, it can display the image correctly. But I need to separate the views.
I have no idea what's wrong in this MVVM code....and how to fix it?
Please point me how can I do or let me know what keyword I can search the toturial/sample.
Thank you all.
--
The OpenFile button is on DisplayControlView and display on DisplayView.
The View Schema is as below:
MainWindow.xaml (window)
|
|__ReviewView.xaml (page)
|
|__DisplayControlView.xaml (page)
|
|__DisplayPanelView.xaml (page)
|
|__DisplayView.xaml (page)
--
DisplayControlView.xaml
<Page.DataContext>
<vm:DisplayViewModel/>
</Page.DataContext>
...
<Button x:Name="btnDpOpen" Style="{DynamicResource ButtonStyle}" Width="120" Command="{Binding OpenFile}">
...
--
DisplayView.xaml
<Page.DataContext>
<vm:DisplayViewModel/>
</Page.DataContext>
...
<Image x:Name="imgDisplayView" Source="{Binding ImagePath}">
<Image.RenderTransform>
<TransformGroup>
<TranslateTransform/>
<RotateTransform/>
<ScaleTransform/>
</TransformGroup>
</Image.RenderTransform>
</Image>
...
--
DisplayViewModel.cs
class DisplayViewModel : ViewModelBase
{
private DisplayImageModel image { get; set; }
private ObservableCollection<DisplayImageModel> imagelist = new ObservableCollection<DisplayImageModel>();
public ObservableCollection<DisplayImageModel> ImageList
{
get { return imagelist; }
set
{
imagelist = value;
OnPropertyChanged();
}
}
public string ImagePath
{
get { return image.Path; }
set
{
if (image.Path != value)
{
image.Path = value;
OnPropertyChanged();
}
}
}
public DisplayViewModel()
{
image = new DisplayImageModel();
ImagePath = @"C:\Users\oscartsai\Desktop\lenna.png";
}
public bool CanExecute()
{
return true;
}
public RelayCommand OpenFile
{
get { return new RelayCommand(openFile, CanExecute); }
}
private void openFile()
{
string[] picExtName = new string[] { ".PNG", ".JPG", "JEPG", "BMP" };
OpenFileDialog dlgOpenFile = new OpenFileDialog()
{ Filter = "Picture|*.jpg;*.jpeg;*.bmp;*.png|All File|*.*" };
if (dlgOpenFile.ShowDialog() != true)
{
return;
}
if (picExtName.Any(System.IO.Path.GetExtension(dlgOpenFile.FileName).ToUpper().Contains))
{
ImagePath = dlgOpenFile.FileName;
OnPropertyChanged();
}
}
}
--
ViewModelBase.cs
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void SetValue<T>(ref T property, T value, [CallerMemberName] string propertyName = null)
{
if (property != null)
{
if (property.Equals(value))
{
return;
}
}
property = value;
OnPropertyChanged(propertyName);
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
--
RelayCommond.cs
public class RelayCommand : ICommand
{
readonly Func<bool> _canExecute;
readonly Action _execute;
public RelayCommand(Action execute) : this(execute, null)
{
}
public RelayCommand(Action execute, Func<bool> canExecute)
{
_execute = execute ?? throw new ArgumentNullException("execute");
_canExecute = canExecute;
}
public event EventHandler CanExecuteChanged
{
add
{
if (_canExecute != null) CommandManager.RequerySuggested += value;
}
remove
{
if (_canExecute != null) CommandManager.RequerySuggested += value;
}
}
[DebuggerStepThrough]
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute();
}
public void Execute(object parameter)
{
_execute();
}
}
|
|
|
|
|
You've got a .Contains function with no parameter.
if (picExtName.Any(System.IO.Path.GetExtension(dlgOpenFile.FileName).ToUpper().Contains))
It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it.
― Confucian Analects: Rules of Confucius about his food
|
|
|
|
|
It uses String[].Any() to indicate the parameter.
The problem is it can't display selected image file on DisplayView (page)....
As my original post mention, all the same code can work well in one ViewModel and one View.
When I separate the code to one ViewModel and 3 Views, it can not work as my expected.
It just can show open dialog for selecting file, but display nothing after selection.
I think the problem will be the operation on one View(DisplayControlView) can not effect another View(DisplayView)
|
|
|
|
|
I use code-behind to load images; that works.
I also hook up the "ImageFailed" event; then you know why it's not working (somewhat).
(MVVM has too much "indirection" for my brain).
It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it.
― Confucian Analects: Rules of Confucius about his food
|
|
|
|
|
Quote: DisplayView.xaml
<Page.DataContext>
<vm:DisplayViewModel/>
</Page.DataContext>
...
<Image x:Name="imgDisplayView" Source="{Binding ImagePath}">
<Image.RenderTransform>
<TransformGroup>
<TranslateTransform/>
<RotateTransform/>
<ScaleTransform/>
</TransformGroup>
</Image.RenderTransform>
</Image>
... The problem is that your DisplayPanelView is setting its DataContext to a new instance of your viewmodel. The image path you set on the DataContext of the DisplayControlView will have no effect on the property of the separate viewmodel instance used as the DataContext for DisplayPanelView .
You need both controls to use the same viewmodel instance for their DataContext . Depending on how your ReviewView viewmodel is set up, you probably want to expose a single DisplayViewModel instance as a property on that viewmodel, and have both Display... views bound to that.
For example:
public class ReviewViewModel : ViewModelBase
{
private DisplayViewModel _display = new DisplayViewModel();
public DisplayViewModel
{
get { return _display; }
set { SetValue(ref _display, value); }
}
} ReviewView.xaml:
<views:DisplayControlView DataContext="{Binding Path=DisplayViewModel}" />
<views:DisplayPanelView DataContext="{Binding Path=DisplayPanelView}" /> Remove the <Page.DataContext> from both DisplayControlView and DisplayPanelView pages.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Here is something can't run properly. Is below code is written in NEW class called ReviewViewModel?
public class ReviewViewModel : ViewModelBase
{
private DisplayViewModel _display = new DisplayViewModel();
public DisplayViewModel
{
get { return _display; }
set { SetValue(ref _display, value); }
}
}
But the Intellisense will show warning about the declaration of DisplayViewModel and the function of SetValue is invalid....
What prerequisites are needed for this code?
Sincere thank Richard Master to point me!!
All Views need one ViewModel instance, and I had no idea about how to set one ViewModel instance until this post point me.
And thank Gerry join this discussion.
modified 21-Jun-21 21:36pm.
|
|
|
|
|
In addition:
ReviewView.xaml
<Page.DataContext>
<vm:DisplayViewModel/>
</Page.DataContext>
<Grid Background="{DynamicResource ThirdHueLightBrush}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="280"/>
<ColumnDefinition MinWidth="690"/>
</Grid.ColumnDefinitions>
<Frame Grid.Column="0" Source="Frame/DisplayControlView.xaml"/>
<Frame Grid.Column="1" Source="Frame/DisplayPanelView.xaml"/>
</Grid>
|
|
|
|
|
One thing I see right off the bat is that when you use DataContext you are instantiating DisplayViewModel.
<Page.DataContext>
<vm:DisplayViewModel/>
</Page.DataContext>
You basically created two instances of DisplayViewModel.
One fix would be to instantiate it somewhere else in C# :
DisplayViewModel displayViewModel = new DisplayViewModel();
Then add to each page then for each page in C# on initialization add:
this.DataContext = ????.displayViewModel
Now they will both point to the same instance.
So many years of programming I have forgotten more languages than I know.
|
|
|
|
|
Thank for point me.
Actually, I had solved this problem a few moment ago... XD
Here is my solution:
1. Using singleton-pattern to fix one execution instance
2. At each View code-behind(???.xmal.cs) which needs to using the same ViewModel, I add below code
this.context = viewmodel.instance
BTW, I also ask in below Taiwan IT forum......and self-question at below to show my detail solution XD
[問題] MVVM架構下,如何多個View共用同一個ViewModel變數 - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天[^]
For you reference~~~
Thanks guys again
modified 13-Oct-21 22:12pm.
|
|
|
|
|
I have also seen static's used. Not a "static" fan but it works. Static's have there place. The reason Serilog is so easy to use and hence popular is because of static's.
So many years of programming I have forgotten more languages than I know.
|
|
|
|
|
I have a simple login window with Company, User Name, and Password. There is a Remember Me checkbox, and if the user checks it, then I pre-fill in the Company and User Name the next time they run the app. In that case, I want to set focus to the Password field.
In the Window's XAML I have
FocusManager.FocusedElement="{Binding FocusedElementName}"
Then in the VM I set the FocusedElementName property to either "company" or "password."
The problem is that the focus is not being set. The code behind is working as expected.
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
The problem is that you're setting the Path of the binding. The FocusedElement property relies on the ElementName of the binding:
FocusManager.FocusedElement="{Binding ElementName=firstButton}" You can't bind the properties of a binding, so you can't do this:
{Binding ElementName={Binding ...}} Short of using the code-behind for the view, the simplest option is probably to use a style with a series of data triggers, as shown in this SO answer[^]:
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding FocusedElement}" Value="First">
<Setter Property="FocusManager.FocusedElement" Value="{Binding ElementName=txtbox1}"/>
</DataTrigger>
</Style.Triggers>
</Style>
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
I have a style FooStyle with some properties and an animation.
I have two other styles Bar1Style and Bar2Style which is based on the FooStyle and sets some properties. I would like to alter the the values in the animation for the Bar-styles.
In the animation I'm altering the buttons ScaleX and ScaleY values with the MouseIsOver trigger.
In the code bellow you notice the values FrameOneValue and FrameTwoValue .
<Style TargetType="Button" x:Key="FooStyle">
<Style.Resources>
<system:Double x:Key="FrameOneValue">1.0</system:Double>
<system:Double x:Key="FrameTwoValue">1.05</system:Double>
</Style.Resources>
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="RenderTransformOrigin" Value="0.5 0.5" />
<Setter Property="RenderTransform">
<Setter.Value>
<TransformGroup>
<ScaleTransform/>
</TransformGroup>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
<EasingDoubleKeyFrame KeyTime="0:0:0.1" Value="{DynamicResource FrameOneValue}"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="{DynamicResource FrameTwoValue}"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
<EasingDoubleKeyFrame KeyTime="0:0:0.1" Value="{DynamicResource FrameOneValue}"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="{DynamicResource FrameTwoValue}"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
<EasingDoubleKeyFrame KeyTime="0:0:0.1" Value="{DynamicResource FrameTwoValue}"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="{DynamicResource FrameOneValue}"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
<EasingDoubleKeyFrame KeyTime="0:0:0.1" Value="{DynamicResource FrameTwoValue}"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="{DynamicResource FrameOneValue}"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style> In the Bar1Style and Bar2Style styles I would like to alter the values for FrameOneValue and FrameTwoValue to suit these styles. As the XAML-code to setup for the animation is quite large I would like to have have the definition in the FooStyle .
The Bar1Style and Bar2Style might look like this:
<Style TargetType="{x:Type Button}" x:Key="Bar1Style" BasedOn="{StaticResource FooStyle}">
<Style.Resources>
<system:Double x:Key="FrameOneValue">2.0</system:Double>
<system:Double x:Key="FrameTwoValue">2.05</system:Double>
</Style.Resources>
<Setter Property="Background" Value="Blue" />
</Style>
<Style TargetType="{x:Type Button}" x:Key="Bar2Style" BasedOn="{StaticResource FooStyle}">
<Style.Resources>
<system:Double x:Key="FrameOneValue">3.0</system:Double>
<system:Double x:Key="FrameTwoValue">3.05</system:Double>
</Style.Resources>
<Setter Property="Background" Value="Red" />
</Style> I would then use this like:
<Window x:Class="Main.MainWindow"
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:local="clr-namespace:Main"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<StackPanel Orientation="Vertical">
<Button Content="btn1" Style="{DynamicResource FooStyle}" />
<Button Content="btn2" Style="{DynamicResource Bar1Style}" />
<Button Content="btn2" Style="{DynamicResource Bar2Style}" />
</StackPanel>
</Window> But this fails hard due to:
Cannot freeze this Storyboard timeline tree for use across threads Which seems to be due to I have specified DynamicResource in the FooStyle .
Which means that I cannot specify values for an animation dynamically in the Bar1Style and Bar2Style styles
Is there some way to solve this?
It's very annoying to have an entire setup of the animation for each style. I just want to alter the values in the Bar-style.
|
|
|
|