• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: MultiBinding
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: MultiBinding


  • Subject: Re: MultiBinding
  • From: "email@hidden" <email@hidden>
  • Date: Tue, 29 Oct 2013 18:15:13 +0000

On 28 Oct 2013, at 20:35, email@hidden wrote:

> On 28 Oct 2013, at 17:52, Gerd Knops <email@hidden> wrote:
>
>> In Interface Builder text fields you can use "Value with Pattern" to combine multiple properties into a single output. Alternatively in code you can do something like this:
>>
>> Gerd
>>
>
> Thanks Gerd
>
> Value with Pattern works as advertised for NSTextField.
> Unfortunately I am binding to an NSPopupButton which lacks this binding.
>
> XAML bindings, though similar in nature to Cocoa bindings, are somewhat more flexible I think.
> The following illustrates more or less what I need to emulate.
>
> The converter (eqv to the value transformer) operates on self.name and PeriodTypeComboBox.SelectedItem.Name
>
> <ComboBox.ItemTemplate>
> 	<DataTemplate>
> 		<TextBlock>
> 			<Run>Based on a</Run>
> 			<Run>
> 				<Run.Text>
> 					<MultiBinding Converter="{StaticResource StringReplaceConverter}" ConverterParameter="Period">
> 						<Binding Path="Name" />
> 						<Binding ElementName="PeriodTypeComboBox" Path="SelectedItem.Name" />
> 					</MultiBinding>
> 				</Run.Text>
> 			</Run>
> 		</TextBlock>
> 	</DataTemplate>
> </ComboBox.ItemTemplate>
>
My solution to providing some sort of emulation of the above behaviour is:

1. Define a NSObject category property bindingDelegate implemented as an associated object. All objects that want to make use of delegate based binding must have this defined.
    eg: [myArray makeObjectsPerformSelector:@selector(setBindingDelegate:) withObject:self]
    myArray supplies content to myArrayController.

2. Use a custom binding key path, bind=. To bind to -name via the delegate the binding key path is bind=name.
   I could have used bind@name but I thought it would start to get confused with the existing usage of @ in bindings.

3. Define a category based override of - (id)valueForUndefinedKey:
    The override looks for the delegate prefix and if found calls the delegate method - (id)boundObject:(id)boundObject valueForUndefinedKey:(NSString *)key options:(NSDictionary *)options;
    The delegate can construct the binding value with arbitrary complexity.

Usage is simple:

1. Set the bindingDelegates on myArray (objects of type MyBoundData) as shown above.
2. Set the NSPopupButton ContentValues binding to myArrayController.arrangedObjects.bind=name
3. Implement the binding delegate method:

- (id)boundObject:(id)boundObject valueForUndefinedKey:(NSString *)key options:(NSDictionary *)options
{
    id value = nil;
    Class boundClass = [boundObject class];

    if (boundClass == [MyBoundData class]) {

        // bound with bind=name
        if ([key isEqualToString:@"name"]) {
            NSString *stringValue = [NSString stringWithFormat:@"Based on a %@", [boundObject valueForKey:key]];	// transform the value
            NSString *periodType = self.periodTypePopupButton.titleOfSelectedItem;	// Modify based on another control
            value = [stringValue stringByReplacingOccurrencesOfString:@"Periodly" withString:periodType];
        }
    }

Note that the bind=name syntax could be extend to bind{key:value}=name to allow for passing additional options to the binding delegate.

Jonathan

/*==============================
NSObject+BindingSupportDelegate.h
==============================*/

@protocol BPBindingSupportDelegate <NSObject>
@required

/*!

 Delegate returns a computed value for the bound object key path.

 */
- (id)boundObject:(id)boundObject valueForUndefinedKey:(NSString *)key options:(NSDictionary *)options;
@end


@interface NSObject (BindingSupportDelegate)

- (id)extValueForKey:(NSString *)key withTransformerForName:(NSString *)transformerName;

/*!

 A delegate object dedicated to provide binding support

 */
@property (nonatomic, retain) id <BPBindingSupportDelegate> bindingDelegate;

@end

/*==============================
NSObject+BindingSupportDelegate.m
==============================*/

// The minimal form acceptable form. A  more general form could be bind{key:value,...}=
NSString *BindingSupportDelegatePrefix = @"bind=";

@implementation NSObject (BrightPay)

#pragma mark -
#pragma mark Binding delegate

- (void)setBindingDelegate:(id)object
{
    objc_setAssociatedObject(self, @selector(bindingDelegate), object, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (id)bindingDelegate {
    return objc_getAssociatedObject(self, @selector(bindingDelegate));
}

#pragma mark -
#pragma mark KVC key handling

- (id)valueForUndefinedKey:(NSString *)key
{
    id value = nil;

    // Look for delegate binding prefix
    NSRange prefixRange = [key rangeOfString:BindingSupportDelegatePrefix];
    if (prefixRange.location == 0 && [key length] > prefixRange.length && self.bindingDelegate) {

        NSString *targetKey = [key substringFromIndex:prefixRange.length];
        value = [self.bindingDelegate boundObject:self valueForUndefinedKey:targetKey options:nil];
    }

    // Reproduce default implementation behaviour
    if (!value) {
        [NSException exceptionWithName:NSUndefinedKeyException
                                reason:@"Key not found"
                              userInfo:@{ @"NSTargetObjectUserInfoKey": self , @"NSUnknownUserInfoKey": key}
         ];
    }

    return value;
}
@end



_______________________________________________

Cocoa-dev mailing list (email@hidden)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:

This email sent to email@hidden


References: 
 >MultiBinding (From: "email@hidden" <email@hidden>)
 >Re: MultiBinding (From: Gerd Knops <email@hidden>)
 >Re: MultiBinding (From: "email@hidden" <email@hidden>)

  • Prev by Date: Re: Insane Spaces
  • Next by Date: Codesigning 3rd party framework
  • Previous by thread: Re: MultiBinding
  • Next by thread: NSWindow Level Side Effect - PopUp to Normal
  • Index(es):
    • Date
    • Thread