I need a WPF control that functions similar to the 'Resolve Conflicts' window in TFS, and other similar source control systems.
I have the following classes
public class Conflict:INotifyPropertyChanged
{
private string _name;
private List<Resolution> _resolutions;
private bool _focused;
private bool _hasResolutions;
public string Name
{
get { return _name; }
set
{
_name = value;
OnPropertyChanged("Name");
}
}
public List<Resolution> Resolutions
{
get { return _resolutions; }
set
{
_resolutions = value;
OnPropertyChanged("Resolutions");
}
}
public bool Focused
{
get { return _focused; }
set {
_focused = value;
OnPropertyChanged("Focused");
}
}
public bool HasResolutions
{
get { return _resolutions.Any(); }
set
{
_hasResolutions = value;
OnPropertyChanged("HasResolutions");
}
}
}
public class Resolution
{
public string Name { get; set; }
public void Resolve()
{
//Logic goes here
}
}
This almost identical to the functionality of the Team Foundation Server (TFS) 'Resolve Conflict' window shown below:
For each row in the image above, it is the same as my Conflcit object, and for each of the buttons, would be one of the Resolution objects on the Conflict object.
My plan was to bind my List to a ListView, and then write a custom template or whatever to hide/show the buttons below it based on if it was selected or not.
To try to simplify what I need to accomplish, I have a List and I want to bind it to a control, and it look as close to the image above as possible.
How would I accomplish this and XAML and the code behind?
Here is an example of how you can dynamically create a data template, and add buttons based on your Conflict objects:
public DataTemplate BuildDataTemplate(Conflict conflict)
{
DataTemplate template = new DataTemplate();
// Set a stackpanel to hold all the resolution buttons
FrameworkElementFactory factory = new FrameworkElementFactory(typeof(StackPanel));
template.VisualTree = factory;
// Iterate through the resolution
foreach (var resolution in conflict.Resolutions)
{
// Create a button
FrameworkElementFactory childFactory = new FrameworkElementFactory(typeof(Button));
// Bind it's content to the Name property of the resolution
childFactory.SetBinding(Button.ContentProperty, new Binding("Name"));
// Bind it's resolve method with the button's click event
childFactory.AddHandler(Button.ClickEvent, new Action(() => resolution.Resolve());
// Append button to stackpanel
factory.AppendChild(childFactory);
}
return template;
}
You can do this in many different ways and this is just one of them.
I haven't test it, but this should be enough to get you started :)
Good luck
Related
I have a question. How to bind variables dynamically from ViewModel to View? For now, it not even displayed. If i not using Command, it works great (but of course, i can bind image only once).
My View:
namespace somestuff.View
{
public partial class WindowView : Window
{
public WindowView()
{
this.DataContext = new WindowViewModel();
InitializeComponent();
}
}
}
my View.Xaml (shorten):
<Image Source="{Binding DisplayedImage}"/>
<Button Command="{Binding NewImageCommand}"/>
And my ViewModel:
public WindowViewModel()
{
_canExecute = true;
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public string DisplayedImage //displaying image
{
get { return filepath; }
set { filepath = value; NotifyPropertyChanged(nameof(filepath)); }
}
public string filepath { get; set; } //var for binding
private bool _canExecute;
private ICommand _newImageCommand; //command for button
public ICommand NewImageCommand
{
get
{
return _newImageCommand ?? (_newImageCommand = new Commands.CommandHandler(() => GetImage(), _canExecute));
}
}
public void GetImage() { filepath = Pictures.GetNewImage(); } //command on button click
Can you tell me, why after triggering Command GetImage() on button click the image binded on Image not changed? If i move filepath = Pictures.GetNewImage(); from command (more clear, i not use command) all works great, but i cant re-invoke binding to my Image. Can you tell me, how to bind propertis dynamically into View from View model? When value of variable (in this case, filepath) change, i want to change View control too.
Thanks for any advices.
EDIT:
I have 6 Image Labels. I displaying images in it like that:
public BitmapImage DisplayedHighPerformanceImage
{
get { return kMMHP; }
set { kMMHP = value; NotifyPropertyChanged(nameof(kMMHP)); }
}
So i need filepath to init 6 diffrent bitmaps. Then i work on that bitmaps (for exampe, that kMMHP) So i want to display every new bitmap initialized from kMMHP image.
kMMHP = method1(); //displaying it
//other stuff do with diffrent bmps
kMMHP = method2(); //displaying it after second method with changed values
NotifyPropertyChanged must be called with the name of the property, not the name of its backing field. And in order to fire the change notification event, you have to set the property, not the backing field:
public BitmapImage DisplayedHighPerformanceImage
{
get { return kMMHP; }
set { kMMHP = value; NotifyPropertyChanged(nameof(DisplayedHighPerformanceImage)); }
}
DisplayedHighPerformanceImage = method1();
This code use with code of win form.So I want to use it with DevExpress and the problem is I don't know which tool in DevExpress that I can use instead of this code.I have a class below: Thanks
using System.Drawing;
using System;
namespace Extender
{
public class MenuItem : System.Windows.Forms.ToolStripMenuItem
{
private string _Command;
public string Command
{
get
{
return _Command;
}
set
{
_Command = value;
}
}
private object _Argument;
public object Argument
{
get
{
return _Argument;
}
set
{
_Argument = value;
}
}
private Int16 _ModuleID;
public Int16 ModuleID
{
get
{
return _ModuleID;
}
set
{
_ModuleID = value;
}
}
public MenuItem()
{
}
public MenuItem(string text)
{
this.Text = text;
}
public MenuItem(string text, EventHandler onclick) :
this(text)
{
this.Click += onclick;
}
}
}
And the code below is the method that I use to create menu from database using entity framework with winform
private void LoadMenus(ToolStripItemCollection Menu,string ParentName)
{
using (var ctx = new CambbusEntities())
{
foreach (var obj in ctx.view_ObjectDetails.Where(a => a.ObjectType == "MENU" && a.ParentName==ParentName &&a.LanguageID == Cambbus.Properties.Settings.Default.LanguageID ).OrderBy(a=>a.SortOrder))
{
string mText = obj.ObjectText;
string nName = obj.ObjectName;
if (mText == "-")
continue;
Extender.MenuItem m = new Extender.MenuItem(mText);
m.Alignment = ToolStripItemAlignment.Left;
//m.Text = obj.ObjectText;
//m.Name = obj.ParentName;
m.ModuleID = (Int16)obj.ModuleID;
m.Command = obj.Command;
m.Argument = obj.Argument;
m.Image = App.GetImageByEntity((obj.ImageTag)+"");
if (m.Command!=""){
m.Click += DynamicMenuClick;
}
bool Is4Perm = obj.ModuleID > 0;
if(Is4Perm){
m.Enabled = CurrentUser.CanViewModule((Int16)obj.ModuleID);
}
Int16 shortcutNum = ((Int16)(obj.ShortcutNum));
if (shortcutNum != 0)
{
m.ShortcutKeys = ((System.Windows.Forms.Keys)(Keys.Control)) | ((System.Windows.Forms.Keys)(shortcutNum));
}
Menu.Add(m);
LoadMenus(m.DropDownItems,nName);
}
}
}
The problem is I don't know the properties of DevExpress that can use instead winform. So can I use DevExpress instead of winform?
this is my image of winform
and I want to change to DevExpress same as in picture DevExpress Menu by using my class and method.thanks
DevExpress bars have several types of menu item. Their list is available at The List of Bar Items and Links. Since you need to handle a click on an item, I think you need BarButtonItem. You can set its caption by using the BarButtonItem.Caption property. For a click, handle the BarItem.ItemClick event.
Edited
With DevExpress, you can replace the orange tool bar with a Bar. For this, simply place BarManager on your form. It creates some default bars. Program, Sales, Help, etc. commands can be replaced with BarButtonItems as I described above. Listings and its sub items can be done by using BarSubItem. I see that you have the Windows item. If your application is MDI, I suggest you use BarMdiChildrenListItem. It will automatically generate items for all MDI child forms.
If you need to generate items in code, refer to the BarManager Class help topic that provides some code for this.
I am running into an issue that I have found on some similar post, however, they are not quite the same and I am not quite sure how to apply it to my scenario. They may or may not be the same as my case. So, I am posting my own question here hopefully, I will get an answer to my specific scenario.
Basically, I have a window form with a bunch of controls. I would like to have the ability to bind their Enabled property to a Boolean variable that I set so that they can be enable or disable to my discretion.
public partial class MyUI : Form
{
private int _myID;
public int myID
{
get
{
return _myID;;
}
set
{
if (value!=null)
{
_bEnable = true;
}
}
}
private bool _bEnable = false;
public bool isEnabled
{
get { return _bEnable; }
set { _bEnable = value; }
}
public myUI()
{
InitializeComponent();
}
public void EnableControls()
{
if (_bEnable)
{
ctl1.Enabled = true;
ctl2.Enabled = true;
......
ctl5.Enabled = true;
}
else
{
ctl1.Enabled = false;
ctl2.Enabled = false;
......
ctl5.Enabled = false;
}
}
}
}
The method EnableControls above would do what I need but it may not be the best approach. I prefer to have ctrl1..5 be bound to my variable _bEnable. The variable will change depending on one field users enter, if the value in the field exists in the database, then other controls will be enabled for user to update otherwise they will be disabled.
I have found a very similar question here
but the data is bound to the text field. How do I get rid of the EnableControls method and bind the value of _bEnabled to the "Enabled" property in each control?
Go look into the MVVM (Model - View - ViewModel) pattern, specifically its implementation within Windows Forms. Its much easier to apply it to a WPF/Silverlight application, but you can still use it with Windows Forms without too much trouble.
To solve your problem directly, you will need to do 2 things:
Create some class that will hold your internal state (i.e. whether or not the buttons are enabled). This class must implement INotifyPropertyChanged. This will be your View Model in the MVVM pattern.
Bind an instance of the class from 1.) above to your Form. Your form is the View in the MVVM pattern.
After you have done 1 and 2 above, you can then change the state of your class (i.e. change a property representing whether a button is enabled from true to false) and the Form will be updated automatically to show this change.
The code below should be enough to get the concept working. You will need to extend it obviously, but it should be enough to get you started.
View Model
public class ViewModel : INotifyPropertyChanged
{
private bool _isDoStuffButtonEnabled;
public bool IsDoStuffButtonEnabled
{
get
{
return _isDoStuffButtonEnabled;
}
set
{
if (_isDoStuffButtonEnabled == value) return;
_isDoStuffButtonEnabled = value;
RaisePropertyChanged("IsDoStuffButtonEnabled");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
View
public class View : Form
{
public Button DoStuffButton { get; set; }
public void Bind(ViewModel vm)
{
DoStuffButton.DataBindings.Add("Enabled", vm, "IsDoStuffButtonEnabled");
}
}
Usage
public class Startup
{
public ViewModel ViewModel { get; set; }
public View View { get; set; }
public void Startup()
{
ViewModel = new ViewModel();
View = new View();
View.Bind(ViewModel);
View.Show();
ViewModel.IsDoStuffButtonEnabled = true;
// Button becomes enabled on form.
// ... other stuff here.
}
}
Maybe you can try this approach: in your isEnabled property's setter method, add an if statement:
if(_bEnable) EnableControls();
else DisableControls();
And if your control names are ctl1,ctl2... etc. you can try this:
EnableControls()
{
for(int i=1; i<6;i++)
{
string controlName = "ctl" + i;
this.Controls[controlName].Enabled = true;
}
}
And apply the same logic in DisableControls
If you have more controls in future this could be more elegant.
I am writing an application which is going to allows users to change the properties of a text box or label and these controls are user controls. Would it be easiest to create a separate class for each user control which implements the properties I want them to be able to change and then bind those back to the user control? Or is there another method I am overlooking?
Create a custom Attribute, and tag the properties you want the user to edit with this attribute. Then set the BrowsableAttribute property on the property grid to a collection containing only your custom attribute:
public class MyForm : Form
{
private PropertyGrid _grid = new PropertyGrid();
public MyForm()
{
this._grid.BrowsableAttributes = new AttributeCollection(new UserEditableAttribute());
this._grid.SelectedObject = new MyControl();
}
}
public class UserEditableAttribute : Attribute
{
}
public class MyControl : UserControl
{
private Label _label = new Label();
private TextBox _textBox = new TextBox();
[UserEditable]
public string Label
{
get
{
return this._label.Text;
}
set
{
this._label.Text = value;
}
}
[UserEditable]
public string Value
{
get
{
return this._textBox.Text;
}
set
{
this._textBox.Text = value;
}
}
}
I'm writing a desktop application in Visual Studio 2008 / C#
I finished (mostly) writing an engine which generates a working schedule for the week for a small company; a form of a course-scheduling problem
Right now I'm designing a form in which the user can determine the initial parameters, or criteria, for the engine to adhere to (as some settings are optional)
I've got a class named EngineParameters, which holds all of those settings.
For the purpose of databinding, I created a bndEngineParameters class, which encapsulates all the relevant fields with getters and setters
public class bndEngineParameters
{
private engineParameters _parameters;
public bndEngineParameters(engineParameters ep)
{
this._parameters = ep;
}
public bool avoidGrouping
{
get { return _parameters.avoidGrouping; }
set { _parameters.avoidGrouping = value; }
}
public bool avoidWeekends
{
get { return _parameters.avoidWeekends; }
set { _parameters.avoidWeekends = value; }
}
public bool keyFlow
{
get { return _parameters.keyFlow; }
set { _parameters.keyFlow = value; }
}
public bool keyFlowAssistants
{
get { return _parameters.keyFlowAssistants; }
set { _parameters.keyFlowAssistants = value; }
}
}
It's not complete - there will be int values (maximum number of hours one can work etc.); I want those bool values to be bound to checkboxes on my form
And it's at that trivial task where I surprisingly ran into problems
Using "Add New DataSource" wizard, I created a binding source
private System.Windows.Forms.BindingSource bndEngineParametersBindingSource;
I then bound the Checked property of my Checkbox to the respective property of my binding source:
I implemented a local variable boundParameters so that I get an access to the parameters set by the user
public partial class formGenerateRota : Form
{
public bndEngineParameters boundParameters;
// (...)
public formGenerateRota()
{
InitializeComponent();
}
private void formGenerateRota_Load(object sender, EventArgs e)
{
boundParameters = new bndEngineParameters(new engineParameters());
bndEngineParametersBindingSource.Add(boundParameters);
}
// (...)
}
And what? Nothing happens. There is an bndEngineParameters object under bndEngineParametersBindingSource.Current (in run-time of course), but the avoidWeekends value never changes (when I check the checkbox on and off), and the bndEngineParametersBindingSource_CurrentItemChanged event is never fired
What's wrong?
SORRY! it does change, but only after the checkbox loses focus (after validation).
I'm stupid sometimes
If I'm doing something wrong anyway (I'm not any good with data binding), I'd very much appreciate if you point it out of course!
Two common issues:
set the DataSourceUpdateMode to OnPropertyChanged
(optional) to receive changes from the object, implement the {name}Changed event pattern or INotifyPropertyChanged
To be honest though, I'm sure most of that isn't necessary; you should just be able to say:
myCheckbox.Bindings.Add("Checked", myEngineParameters, "avoidWeekends",
false, DataSourceUpdateMode.OnPropertyChanged);
Full example:
using System;
using System.Diagnostics;
using System.Windows.Forms;
class EngineParameters {
private bool avoidWeekends;
public bool AvoidWeekends {
get { return avoidWeekends; }
set {
avoidWeekends = value;
Debug.WriteLine("AvoidWeekends => " + value);
}
}
}
static class Program {
[STAThread]
static void Main() {
Application.EnableVisualStyles();
using(Form form = new Form())
using (CheckBox myCheckbox = new CheckBox()) {
EngineParameters myEngineParameters = new EngineParameters();
myEngineParameters.AvoidWeekends = true;
form.Controls.Add(myCheckbox);
myCheckbox.DataBindings.Add("Checked", myEngineParameters, "AvoidWeekends",
false, DataSourceUpdateMode.OnPropertyChanged);
Application.Run(form);
}
}
}
Instead of this:
bndEngineParametersBindingSource.Add(boundParameters);
do this:
bndEngineParametersBindingSource.DataSource = boundParameters;