I have created a lookless control using silverlight 4. This control contains a textbox which the user will type data into and a button that increases the size of the textbox by increasing the MinHeight of the control by 10 each time it is pressed (I have set the textbox to stretch so it grows with the control).
This bit works fine but I now want to extend the controls functionality by adding another textbox that will display the current MinHeight of the control which I dont seem to be able to do. I have been trying
Text="{Binding RelativeSource={RelativeSource Self}, Path=MinHeight, Mode=TwoWay}">
Im not sure why but this always shows as 0
Update
In my attempts to resolve I tried chaging the name of the source textbox to PART_sourceData and just to see if the binding was correct I set the path to the text property. This appears to bring through the text of the sourcedata as I would expect
Text="{Binding Mode=TwoWay, ElementName=PART_sourceData, Path=Text}"
My next step was to change the path to Height
Text="{Binding Mode=TwoWay, ElementName=PART_sourceData, Path=Height}"
But this returns NaN. Therefore I tried MinHeight
Text="{Binding Mode=TwoWay, ElementName=PART_sourceData, Path=MinHeight}"
This always returns 0 even though the code behind has a valid number. Whats going wrong? Becuase the text comes through properly I beleive the binding to be correct but whats wrong with getting the height?
By binding to RelativeSource Self you are looking at that controls MinHeight. You will need to name your original TextBox with the x:Name attribute, then use ElementName binding.
Ok I have a solution. Not the best but it works!
I have had to create a new dependancy property
public static readonly DependencyProperty EditorHeightProperty =
DependencyProperty.Register("EditorHeight", typeof(string), typeof(EditorControl), new PropertyMetadata(default(string)));
public string EditorHeight
{
get { return (string)GetValue(EditorHeightProperty); }
set { SetValue(EditorHeightProperty, value); }
}
Then I bind the text to this property using
Text="{TemplateBinding EditorHeight}"
Related
I have a CarouselView with ItemTemplate containing a Label and a Grid. Outside of that CarouselView, I want to make a button to modify Carousel's current item's Grid's visibility. Because it's inside ItemTemplate, I can't use x:Name to refer to that specific Grid, so how can I refer to the current item's Grid so I can change its property value? Thank you.
You will want to do that through databinding. As you already mentioned, you can't use x:Name. This is because you're inside of a template. The value in x:Name would be duplicated for each time that template is applied to a concrete item in your list, in this case a CarouselView. Moreover; if you use virtualization for that list, a template might not even exist at all at that point in time. All reasons why you can't use x:Name to reference anything inside of a template.
I don't have any info about the code you want to use this with, so I'll make something up.
If the backing collection for your CarouselView is a ObservableCollection<MyItem>, then your CarouselView might look something like this:
<!-- Databinding scope here is MyViewModel -->
<CarouselView ItemsSource="{Binding MyItemsCollection}">
<CarouselView.ItemTemplate>
<!-- Databinding scope here is MyItem -->
<DataTemplate>
<Button Text="Delete" IsVisible="{Binding CanDelete}" />
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
So you will have a backing view model which has a MyItemsCollection, and your page (that holds the CarouselView) has set the BindingContext to a new instance of MyViewModel:
public class MyViewModel
{
public ObservableCollection<MyItem> MyItemsCollection { get; set; } = new ObservableCollection<MyItem>();
private void LoadData()
{
var items = _myItemService.GetItems();
foreach (var item in items)
{
MyItemsCollection.Add(item);
}
}
}
Whenever you want to influence the IsVisible you will want to set the CanDelete of the MyItem that it's about to false. Let's assume MyItem looks like this:
public class MyItem
{
public bool CanDelete { get; set; }
}
You will need to implement the INotifyPropertyChanged interface on it so that the UI will pick up on any changes that are made to property values.
Now whenever you set the CanDelete of a certain instance of MyItem to false, that will change your UI. E.g.: MyItemsCollection[3].CanDelete = false;
On my YouTube channel I added a playlist with videos about data binding which might help in cases like these.
PS. At the time of writing IsVisible is bugged in .NET MAUI
I have the following TextEdit, bound to a nullable field (Value1):
<dxe:TextEdit EditValue="{Binding Path=Data.Value1, TargetNullValue={x:Null}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" EditValueType="{x:Type sys:Double}" Mask="##.# miles" />
When I hit BackSpace, it shows the remainig mask part (like this: . miles), and its EditValue is set to 0 in the background (which is wrong as it is bound to a nullable field)
I intend to make the EditValue to be null when BackSpace or Delete is used.
How can I do it without a converter or a KeyPress event handler?
This is in fact possible, all you need to do is to set AllowNullInput to true. You may want also to change your mask so that it does not show only the text . miles when you delete every value.
Here is my sample:
<Grid Background="DimGray">
<dxe:TextEdit EditValue="{Binding Path=Value, TargetNullValue={x:Null},
Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"
MaskType="Numeric"
EditValueType="{x:Type sys:Double}"
AllowNullInput="True"
Mask="#0.0 miles"
VerticalAlignment="Center"/>
</Grid>
Hope this helps!
I'm having a problem with showing Dialogs from a View Model. The problem is that the "underlying content is not dimmed and disabled" as the documentation says it should be. If I click on the underlying view the button in the dialog wired to the closed command is sometimes disabled and the user is not able to click it.
I defined the DialogHost in my MainView like this (also tried it in the ShellView):
<materialDesign:DialogHost
HorizontalAlignment="Center"
VerticalAlignment="Center"
CloseOnClickAway="True" />
From my MainViewModel I show the dialog like this:
Dim errView As New ErrorView
Dim res = Await DialogHost.Show(errView)
I wired up the close command on a button in the ErrorView dialog like this:
Command="{x:Static materialDesign:DialogHost.CloseDialogCommand}"
You problem is with the definition of DialogHost; you have it as an empty element.
The DialogHost is a ContentControl. Everything inside is what will become dimmed. So you define it at the root of your main Window/Page XAML, a bit more like:
<materialDesign:DialogHost CloseOnClickAway="True">
<StackPanel>
<TextBlock>Hello World</TextBlock>
<TextBlock>This is the main content of my application</TextBlock>
</StackPanel>
</materialDesign:DialogHost>
Our group is working on a Custom Activity Designer around our Email activity. It's a pretty straight forward designer, allow the user to enter settings / creds, but instead of cluttering the activity designer with all the settable options, we thought about putting some settings in a dialog window. (Which opens when you click the button beside the server address box).
Some of our email activity properties are InArguments so we are trying to make use of the ExpressionTextBox to display these values without much luck. The main problem is we aren't sure how to properly set up the binding and the OwnerActivity on the ExpressionTextBox. In the Activity Designer's xaml this is simply done by setting Expression=ModelItem.Property using a converter for the InArgument and setting the OwnerActivity=ModelItem, like this:
<view:ExpressionTextBox HintText="Enter a VB Expression" Expression="{Binding ModelItem.ServerAddress, ConverterParameter=In, Converter={StaticResource ArgumentToExpressionConverter}, Mode=TwoWay}" ExpressionType="{x:Type system:String}" OwnerActivity="{Binding ModelItem}" Margin="2" MaxLines="1" />
If anyone has any ideas on how we could accomplish this in a dialog, please advise.
Well, this is more a WPF\MVVM question than WF4, really.
When developing custom activities designers you just have to keep one thing in mind: any change made on designer\dialog should be reflected on ModelItem. Either through XAML binding expressions or through code on ModelItem.Properties property.
Now, when and how you do it, there are several answers to that but that's really an implementation detail and depends on how you want to do it.
Lets assume you're showing the dialog on button-beside-the-server-address-box click. And lets also assume you've access to dialog textboxes through their name. At that point, you've access to ModelItem so just set its properties as needed:
private void ButtonNextToServerAddressBox_OnClick(object sender, RoutedEventArgs e)
{
var dialog = new ServerAddressEditor();
var result = dialog.ShowDialog();
if (result ?? false)
{
ModelItem.Properties["Server"].SetValue(new InArgument<string>(dialog.ServerTextBox.Text));
ModelItem.Properties["Port"].SetValue(new InArgument<string>(dialog.PortTextBox.Text));
// ... set all other properties
}
}
Now, if you are using any other pattern, or you want pure MVVM, it can be a little more tricky because of how ModelItem works. But this is a totally fine approach.
I resolved this by creating a property in the dialog's ViewModel to hold the Activity Designer's ModelItem.
public ModelItem OwnerActivity {
get { return _OwnerActivity; }
set { _OwnerActivity = value; }
}
vm.OwnerActivity = this.DataContext.ModelItem;
I then set the Xaml for the Expression Text Box in my dialog to binding to this:
<view:ExpressionTextBox HintText="Enter a VB Expression" Expression="
{Binding Path=OwnerActivity.ServerAddress, ConverterParameter=In, Converter=
{StaticResource ArgumentToExpressionConverter}, Mode=TwoWay}" ExpressionType="
{x:Type system:String}" OwnerActivity="{Binding OwnerActivity}" Margin="2"
MaxLines="1" />
Because I'm now binding directly to the ModelItem from the Activity Designer, any change made to the ModelItem property from the dialog is ALWAYS committed, even if you choose to Cancel from the dialog. To wire up the Ok/Cancel buttons so they work accordingly, I did the following in the dialog:
// declare a ModelEditingScope to make changes transactional
private ModelEditingScope _editScope;
// add this to the constructor of the dialog to begin transactional edits on the ModelItem
_editScope = editorViewModel.OwnerActivity.BeginEdit();
// ok & cancel button click event to commit or revert the changes.
private void OK_Click(object sender, RoutedEventArgs e)
{
_editScope.Complete();
this.DialogResult = DialogResult.OK;
this.Close();
}
private void Cancel_Click(object sender, RoutedEventArgs e)
{
_editScope.Revert();
this.DialogResult = DialogResult.Cancel;
this.Close()
}
I created a class CustomCombo.as that extends ComboBox. What is happening is that the CustomCombo combobox is showing as being editable. I do not want this and I cant find the properties to set the editable to false.
I also tried setting the combobox's textInput.editable control to false, but to no avail.
Any help would be greatly appreciated.
CustomCombo.as
package custom {
import spark.components.ComboBox;
public class CustomCombo extends ComboBox {
public function CustomCombo() {
super();
// this.editable = false; //<-- THIS DOESNT WORK ***Access of possibly undefined property editable through a reference with static type custom:CustomCombo
// this.textInput.editable = false; //<-- THIS DOESNT WORK ***Cannot access a property or method of a null object reference
}
}
}
After rummaging through the Flex 4 API I found that they suggest to use the DropDownList control. From what I can see is that they removed the editable property from the ComboBox control in Flex 4, but I may be wrong.
I implemented DropDownList and that solved my problem.
I see that you're using spark and not mx. The editable property I referred to is applicable only to mx based list. In spark, ComboBox extends DropDownListBase and is editable by default.
The ComboBox control is a child class of the DropDownListBase control. Like the DropDownListBase control, when the user selects an item from the drop-down list in the ComboBox control, the data item appears in the prompt area of the control.
One difference between the controls is that the prompt area of the ComboBox control is implemented by using the TextInput control, instead of the Label control for the DropDownList control. Therefore, a user can edit the prompt area of the control to enter a value that is not one of the predefined options.
For example, the DropDownList control only lets the user select from a list of predefined items in the control. The ComboBox control lets the user either select a predefined item, or enter a new item into the prompt area. Your application can recognize that a new item has been entered and, optionally, add it to the list of items in the control.
The ComboBox control also searches the item list as the user enters characters into the prompt area. As the user enters characters, the drop-down area of the control opens. It then and scrolls to and highlights the closest match in the item list.
So ideally, you should be using DropDownList in this case.
You're getting null error when trying to access textInput from the constructor because it hasn't been created yet. In mx based controls (Flex-3), you can access it from the creationComplete handler; I'm not quite sure how to do it for spark based controls.
Update: I think I've figured out how to access skin parts in spark (though you might wanna use the DropDownBox instead). You have to override the partAdded method.
override protected function partAdded(partName:String, instance:Object):void
{
super.partAdded(partName, instance);
if (instance == textInput)
{
textInput.editable = false;
}
}
There's one catch though: it may not work in this case. The source code of ComboBox.as says that
the API ignores the visual editable and selectable properties
So DropDownList it is!
Initial answer, posted for mx ComboBox.
This shouldn't happen as the default value of the editable property is false.
Try explicitly setting the value to false from the constructor.
public function CustomCombo() {
super();
this.editable = false;
}